React Reducer 真的应该是一个纯函数吗? [英] Should React Reducer really be a pure function?
问题描述
据说useReducer中使用的reducer函数是纯函数.如果我没记错的话,它的行为仅取决于它的输入参数——所以用相同的输入参数调用它两次具有相同的结果."(来自此处).还有(来自这里):
<块引用>减速器应该:
永远不要改变它的参数
从不产生副作用(API 调用不会改变任何东西)
永远不要调用非纯函数,即根据输入以外的因素(例如 Date.now() 或 Math.random())改变其输出的函数
关于这个我有两个问题:
- 谁能解释为什么reducer必须是纯函数?例如如果在接收相同输入时返回两个不同的输出,会出现什么问题?或者,如果它有副作用会怎样?
- 考虑以下示例代码:
导出函数 MyComponent(props: IPropTypes) {const reducer = (prevState, action) =>{newState = deepClone(prevState);newState.count = newState.count + props.count;返回新状态;}const [状态,调度] = useReducer(reducer, ....);返回 (<div>...</div>)}
我是否正确地认为上述 reducer 不是一个好的 reducer,因为它也依赖于 props(这不是它的输入)?为什么这是一件坏事?
参考官方Redux 文档,使用纯函数编写 reducer 会增加您重用 reducer 的机会.
我认为您可以通过将 props.count 作为函数的参数,将它放在 action 对象中来使您的 reducer 变得纯粹.我更喜欢制作 payload
字段.
这是我写的工作代码:代码和盒子,这就是我改变你的组件的方式:
const reducer = (state, action) =>{开关(动作.类型){案例增量":返回 {...状态,计数:state.count + action.payload};默认:返回状态;}};导出默认值(道具)=>{const [state, dispatch] = useReducer(reducer, { count: 0 });const 增量 = () =>dispatch({ type: "INCREMENT", payload: props.count });返回 (<div><p>当前:{state.count}</p><button onClick={increment}>Increment</button>
);}
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:
- Can any one explain why the reducer must be a pure function? e.g. what can go wrong if it returns two different outputs while receiving the same input? Or, what happens if it has side-effects?
- Consider the following sample code:
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?
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>
);
}
这篇关于React Reducer 真的应该是一个纯函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!