是的,reducer 是同步运行的纯函数,因此任何单个调度的动作都会在下一个动作之前处理。
这可能有助于您更好地理解 reducer 功能:https://redux.js.org/basics/data-flow
功能组件主体是完全同步的,所以一切都是按照每个渲染周期调用的顺序进行的。链接来自 redux,但 reducer 的工作方式相同,并且可以互换,即 reducer 函数具有签名 (state, action) => nextState。
所有钩子值都在渲染周期之间起作用,这意味着,在渲染周期中“排队”的所有状态更新和调度动作都按该顺序进行批处理。
给定:
dispatch('a')
dispatch('b')
dispatch('b') 减速器案例将在dispatch('a') 案例完成后运行。
更新
您可以查看useState 和useReducer 挂钩的源代码,看看它们将以相同的同步顺序方式处理更新。
Dispatch
type Dispatch<A> = A => void;
这里可以看到dispatch是一个同步函数。
useState
export function useState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
useReducer
export function useReducer<S, I, A>(
reducer: (S, A) => S,
initialArg: I,
init?: I => S,
): [S, Dispatch<A>] {
const dispatcher = resolveDispatcher();
return dispatcher.useReducer(reducer, initialArg, init);
}
useState 和 useReducer 都使用相同的内部调度系统(即resolveDispatcher)。由于useReducer 无法处理异步操作(例如 Redux-Thunks),因此没有其他选项但可以在减速器中同步处理操作之前 em> 处理下一个分派的动作。
更新 2
修改:reducers 和 setStates 结合起来怎么样?是他们的
通话顺序还保留吗?例如,一个 setState、一个 reducer(它使用
setState 中设置的状态值)。
将保持顺序,但您将无法将状态更新加入队列,然后根据更新后的状态调度操作。这是由于 React 状态更新是在 渲染周期之间异步处理的。换句话说,任何setState(newState) 在下一个渲染周期之前都无法访问。
例子:
const [countA, setCountA] = useState(0);
const [countB, dispatch] = useReducer(.....);
...
setCountA(c => c + 1); // enqueues countA + 1, next countA is 1
dispatch(setCountB(countA)); // dispatches with countA === 0
setCountA(c => c + 1); // enqueues countA + 1, next countA is 2
dispatch(setCountB(countA)); // dispatches with countA === 0