Reputation: 127
I am trying to update the input fields values to state using the react context and reducer but I am not able to update the state. Request help with the same.
State function:
const handleChangeFor = input => e => {
{
dispatch({
type: UPDATE_FIELD,
payload: { input, e }
});
}
};
Reducer :
case UPDATE_FIELD:
return {
...state,
[action.payload.input]: action.payload.value
};
Component :
<InputTextContainer>
<InputSelect
value={addOnCategory}
name="addOnCategory"
onChange={handleChangeFor('addOnCategory')}
>
<InputOption value="" style={{ display: 'none' }}>
Please select
</InputOption>
<InputOption>Add On</InputOption>
<InputOption>Flavours</InputOption>
</InputSelect>
</InputTextContainer>
Upvotes: 1
Views: 560
Reputation: 39270
There are 2 things wrong with your code:
const UPDATE_FIELD = 'UPDATE_FIELD';
const reducer = (state, { type, payload }) => {
if (type === UPDATE_FIELD) {
const { input, value } = payload;
return { ...state, [input]: value };
}
};
const handleChangeFor = (input, e) => {
//event will be re used and cause an error
// use value instead of passing event to
// reducer
return {
type: UPDATE_FIELD,
payload: { input, value: e.target.value },
};
};
const PureInput = React.memo(function PureInput({
value,
onChange,
}) {
const r = React.useRef(0);
r.current++;
return (
<label>
pure input rendered: {r.current} times
<input
type="text"
onChange={onChange('pure')}
value={value}
/>
</label>
);
});
const App = () => {
const [state, dispatch] = React.useReducer(reducer, {
name: '',
pure: '',
});
//if you want to optimize you can use useCallback
const handleChange = React.useCallback(
(input) => (e) => dispatch(handleChangeFor(input, e)),
[]
);
return (
<div>
<div>
<input
type="text"
onChange={(e) =>
dispatch(handleChangeFor('name', e))
}
value={state['name']}
/>
</div>
<PureInput
value={state['pure']}
onChange={handleChange}
/>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 1