Reputation: 447
I'm playing around with redux for the first time and I'm finding it fairly confusing haha It's not as simple as it sounds. I have a react project where I have a form that is divided into 3 parts(components). Each of these components has its own state to save the form data of that component.
Here is where I was gonna implement redux.
My goal here is to store the state of all 3 components in a react store. So on submit of each of the 3 form parts, they will all be merged into one big state in a redux store then I can do with it as I please.
Right now I have installed redux, created a store and now I'm lost haha Can anyone help or even direct me to a useful resource? I've looked at the redux documentation and just cannot get my head around it
My form:
return (
<Form onSubmit={this.handleSubmit} className="form">
{/* General Information */}
<FormGroup row>
<Col sm={6}>
<Input type="text" onChange={this.handleChange} name="siteName" id="siteName" placeholder={this.placeholders.siteName}/>
</Col>
<Col sm={6}>
<Input className="form-control" type="select" id="counties" onChange={this.handleChange}>
<option className="selectDefault" disabled value={this.placeholders.siteCounties} selected>{this.placeholders.siteCounty}</option>
{ this.counties.map(c => (<option key={c.value} value={c.value}>{c.display}</option>))}
</Input>
</Col>
</FormGroup>
<FormGroup row>
<Col sm={12}>
<Input type="textarea" onChange={this.handleChange} name="siteAddress" placeholder={this.placeholders.siteAdd} id="siteAddress" />
</Col>
</FormGroup>
<FormGroup row>
<Col sm={6}>
<Input type="email" name="siteEmail" onChange={this.handleChange} id="siteEmail" placeholder={this.placeholders.email} />
</Col>
<Col sm={6}>
<Input type="tel" name="siteNumber" onChange={this.handleChange} id="siteNumber" placeholder={this.placeholders.number}/>
</Col>
</FormGroup>
<FormGroup row>
<Col sm={6}>
<Input type="select" name="siteCat" onChange={this.handleChange} id="siteCat" multiple placeholder={this.placeholders.categories}>
<option className="selectDefault" disabled selected>{this.placeholders.categories}</option>
{ this.categories.map(c => (<option key={c.value} value={c.value}>{c.display}</option>))}
</Input>
</Col>
<Col sm={6}>
<Input type="textarea" name="openTimes" onChange={this.handleChange} id="openTimes" placeholder={this.placeholders.times} />
</Col>
</FormGroup>
<FormGroup row>
<Col sm={6}>
<Input type="textarea" name="fees" onChange={this.handleChange} id="fees" placeholder={this.placeholders.fees}/>
</Col>
<Col sm={6}>
<Input type="text" name="access" onChange={this.handleChange} id="access" placeholder={this.placeholders.access} />
</Col>
</FormGroup>
<hr/>
{/* Location Information */}
<FormGroup row>
<Col sm={6}>
<Input type="text" name="gps" onChange={this.handleChange} id="gps" placeholder={this.placeholders.gps}/>
</Col>
<Col sm={6}>
<Input type="text" name="w3w" id="w3w" onChange={this.handleChange} placeholder={this.placeholders.w3w} />
</Col>
</FormGroup>
<hr/>
<FormGroup row>
<Col sm={12}>
<Input type="textarea" name="txtHeader" onChange={this.handleChange} id="txtHeader" placeholder={this.placeholders.textHeader} />
</Col>
</FormGroup>
<FormGroup row>
<Col sm={12}>
<Input type="textarea" name="txtContent" onChange={this.handleChange} id="txtContent" placeholder={this.placeholders.textContent} />
</Col>
</FormGroup>
<FormGroup check row>
<Col sm={{ size: 10, offset: 2 }}>
<Button disabled={!this.validateForm()} type="submit" className="btn-primary">Tours →</Button>
</Col>
</FormGroup>
</Form>
);
Form state:
constructor(props) {
super(props);
this.state = {
language: this.props.language,
siteName: '',
counties: '',
siteAddress: '',
siteEmail: '',
siteNumber: '',
siteCat: '',
openTimes: '',
fees: '',
access: '',
gps: '',
w3w: '',
txtHeader: '',
txtContent: '',
isLoading: false
};
}
validateForm() {
if (this.state.siteName != '' &&
this.state.siteAddress != '' &&
this.state.siteEmail != '' &&
this.state.siteNumber != '' &&
this.state.openTimes != '' &&
this.state.fees != '' &&
this.state.access != '' &&
this.state.gps != '' &&
this.state.w3w != '' &&
this.state.txtHeader != '' &&
this.state.txtContent != '') {
return true;
} else {
return false;
}
}
handleChange = e => {
this.setState({ ...this.state, [e.target.name]: e.target.value });
console.log(this.state);
}
Upvotes: 0
Views: 76
Reputation: 18674
I would recommend you to take a look at redux-form
.
As you already have redux
as dependency, you can take advantage of all form's abstractions these redux-form
already implemented it for us.
According to your use-case, redux-form
already implemented such form behavior, knows as Wizard Form.
Here's a complete working example: https://redux-form.com/8.1.0/examples/wizard/
Upvotes: 0
Reputation: 2066
redux is a predictable state container that acts as your single point of truth, manipulating your data can be done using actions that are pure functions.
so when you have a state that is shared between your components this is where you need to move this state to redux store, each item in the store has a reducer unless your app is only one thing.
for example, the first thing you need to do is install the needed dependencies :
npm install redux react-redux --save
after its installed create a file named store.js with the following code :
import {combineReducers,createStore} from 'redux'
// Your Reducer
import myReducer from './myreducer'
// we use combineReducers to be able to add more than one.
const reducers = combineReducers({
mystate:myReducer
})
export default createStore(reducers);
then let's create that reducer myreducer.js:
// this is your pure function has 2 params
// first one is the state it immutable
// then the action which is the action you dispatched with its paylod
const myReducer = (state = [], action) => {
switch (action.type) {
case "ADD_ITEM":
// i created a new array and spread the data in it to be immutable
return [...state,action.item]
// you always need this becuse redux will run all the reducers.
default:
return state;
}
}
export default myReducer;
Now get back to the App.js component and make it as the following :
/*
The <Provider /> makes the Redux store available to any nested components that have been wrapped in the connect() function.
Since any React component in a React Redux app can be connected, most applications will render a <Provider> at the top level, with the entire app’s component tree inside of it.
Normally, you can’t use a connected component unless it is nested inside of a <Provider>.
*/
import React, {Component} from 'react';
import {Provider} from 'react-redux'
import store from './store'
export default class App extends Component {
render(){
return (
<Provider store={store}>
// your app
</Provider>
)
}
}
i recommend you to go thrught the quick start (https://react-redux.js.org/introduction/quick-start)
Upvotes: 0