Reputation: 2828
It is said that the reducer function used in useReducer is a pure function. If I'm not wrong, "Its behaviour depends only on its input parameters -- so calling it twice with the same input parameters has the same resulting effect." (from here). And also (from here):
A reducer should:
never mutate its arguments
never generate side-effects (no API calls changing anything)
never call non-pure functions, functions that change their output based on factors other than their input (e.g. Date.now() or Math.random())
I have two questions regarding this:
export function MyComponent(props: IPropTypes) {
const reducer = (prevState, action) => {
newState = deepClone(prevState);
newState.count = newState.count + props.count;
return newState;
}
const [state, dispatch] = useReducer(reducer, ....);
return (<div>
...
</div>)
}
Am I right that the above reducer is not a good reducer because it is also dependent on props (which is not its input)? Why is this a bad thing?
Upvotes: 3
Views: 829
Reputation: 530
Referring the official Redux documentation, writing reducers with pure functions increases the chance you reuse your reducers.
I think you can make your reducer pure, just by giving the props.count as an argument of a function, by putting it inside the action object. I prefer making a payload
field.
Here is a working code I wrote: codesandbox, and this is how I changed your Component:
const reducer = (state, action) => {
switch(action.type){
case "INCREMENT":
return {
...state,
count: state.count + action.payload
};
default:
return state;
}
};
export default (props) => {
const [state, dispatch] = useReducer(reducer, { count: 0 });
const increment = () => dispatch({ type: "INCREMENT", payload: props.count });
return (
<div>
<p>Current: {state.count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
Upvotes: 3