Reputation: 6123
Before asking this I did a Google search and I didn't find any good resource to manage a form only with Redux. All of the examples use redux-forms. It is only one form and I don't want to install that library to use only on one, minimal, small form.
I can't use local state because the user has the option to go to another screen and then be back on the screen which contains the form, so at some point the component could be unmounted and mounted again and I want it to keep its state.
This is the component I have so far and the way I've been working on it:
import { compose } from 'redux';
import { connect } from 'react-redux';
import React from 'react';
import FormField from '../FormField/FormField';
import {
startupThirdStepFormAction,
} from '../../pages/StartupApplication/actions/startupApplicationActions';
const StepThreeForm = ({
startupThirdStepForm,
startupThirdStepFormActionHandler,
}) => (
<>
<Container>
<Row>
<Col>
<Form>
<FormField
value={startupThirdStepForm.firstName}
label="First Name"
controlId="firstName"
onChange={e =>
startupThirdStepFormActionHandler({
firstName: e.target.value,
})
}
/>
<FormField
value={startupThirdStepForm.middleName}
label="Middle Name"
controlId="middleName"
onChange={e =>
startupThirdStepFormActionHandler({
middleName: e.target.value,
})
}
/>
</Form>
</Col>
</Row>
</Container>
</>
);
export default compose(
connect(
store => ({
startupThirdStepForm: store.startupApplicationReducer.startupThirdStepForm,
}),
dispatch => ({
isStepDoneActionHandler: index => {
dispatch(isStepDoneAction(index));
},
startupThirdStepFormActionHandler: form => {
dispatch(startupThirdStepFormAction(form));
},
}),
),
)(StepThreeForm);
Right now as you may see I am trying to send the value to the store like this:
onChange={e =>
startupThirdStepFormActionHandler({
firstName: e.target.value,
})
That is for the firstName
field, but when I do the same for the middleName
field, it obviously cleans the firstName
field.
Here is the reducer:
const initialState = {
startupThirdStepForm: {},
};
const handlers = {
[ActionTypes.STARTUP_THIRD_STEP_FORM](state, action) {
return {
...state,
startupThirdStepForm: action.payload.startupThirdStepForm,
};
},
}
export default createReducer(initialState, handlers);
And the action:
export const startupThirdStepFormAction = startupThirdStepForm => ({
type: ActionTypes.STARTUP_THIRD_STEP_FORM,
payload: { startupThirdStepForm },
});
So what can I do to keep the state of the form fields without cleaning the others?
Upvotes: 0
Views: 609
Reputation: 2535
A very quick suggestion is to create a copy of the state. For you to easily identify what field to update you can add name
and value
inside payload.
onChange={e =>
startupThirdStepFormActionHandler({
name: "firstName"
value: e.target.value,
})
const handlers = {
[ActionTypes.STARTUP_THIRD_STEP_FORM](state, action) {
let newStartupThirdStepForm = Object.assign({}, state.startupThirdStepForm);
newStartupThirdStepForm[action.payload.name] = action.payload.value;
return {
...state,
startupThirdStepForm: newStartupThirdStepForm,
};
},
}
Upvotes: 0
Reputation: 1545
Try doing the following for your reducer instead:
const handlers = {
[ActionTypes.STARTUP_THIRD_STEP_FORM]: (state, action) {
return {
...state,
startupThirdStepForm: {
// to preserve old state
...state.startupThirdStepForm,
// to update with new data
...action.payload.startupThirdStepForm,
},
};
},
}
Upvotes: 1