React Reducer真的应该是一个纯函数吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Reducer真的应该是一个纯函数吗?相关的知识,希望对你有一定的参考价值。
据说useReducer中使用的reducer函数是纯函数。如果我没记错的话,“它的行为仅取决于其输入参数-因此使用相同的输入参数两次调用它会产生相同的结果。” (来自here)。并且(来自here):
减速器应:
从不改变其参数
从不产生副作用(没有API调用会改变任何东西)
从不调用非纯函数,这些函数会根据输入以外的因素更改其输出(例如Date.now()或Math.random())>
我对此有两个问题:
- 任何人都可以解释为什么减速器必须是纯函数吗?例如如果在接收相同输入的同时返回两个不同的输出,怎么办?或者,如果有副作用怎么办?
- 请考虑以下示例代码:
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>)
我对上述减速器不是很好的减速器,因为它也取决于道具(不是道具的输入)吗?为什么这是一件坏事?
参考官方Redux documentation,编写具有纯功能的减速器会增加重用减速器的机会。
[我认为您可以通过将props.count用作函数的参数,并将其放入动作对象中,来使您的reducer变得纯净。我更喜欢制作payload
字段。
这是我编写的有效代码:codesandbox,这就是我更改组件的方式:
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>
);
这样的reducer实际上是一个纯函数,但是由于其他原因是不好的:closures。
export function MyComponent(props)
// Closure on props.count
const reducer = (prevState, action) =>
newState = deepClone(prevState);
newState.count = newState.count + props.count;
return newState;
;
// The reducer assigned **ONCE** on initial render
// for the entire component life (until unmount)
const [state, dispatch] = useReducer(reducer, initialState);
return <div>...</div>;
您可能希望在每个渲染器上减速器都会改变并动态地起作用,但是不会。如果在特定时刻props.count === 5
总是降低newState.count = newState.count + 5;
,这是非常意外的行为。
谁能解释为什么化简器必须是纯函数?例如如果在接收相同输入的同时返回两个不同的输出,怎么办?或者,如果有副作用怎么办?
如果reducer不是纯函数,则具有副作用,即更改某些其他数据(API调用)可能会导致在应用程序中某处出现stale数据。
这是因为化简器是异步的,您的化简器代码可能会完成并在屏幕上显示数据,但是实际上由于API调用并且陈旧了,此数据已经更改,但是您的应用程序没有意识到此更改,因此未获取任何渲染更改UI表示形式。
这确实是一个不好的减速器,因为每次运行时,计数结果都会不同。精简器旨在获取数据并始终返回相同的结果。
想象一下,如果您在此组件中具有其他状态,它可能会以您未曾想到的方式触发reducer,并且计数将在整个渲染过程中发生变化并聚合。
以上是关于React Reducer真的应该是一个纯函数吗?的主要内容,如果未能解决你的问题,请参考以下文章
offer 收割计划你知道为什么 reducer 最好是一个纯函数吗?
offer 收割计划你知道为什么 reducer 最好是一个纯函数吗?
offer 收割计划你知道为什么 reducer 最好是一个纯函数吗?
offer 收割计划你知道为什么 reducer 最好是一个纯函数吗?