私が見ている動作は、多くの人からの主張にもかかわらず、 dispatch
inreact
が同期していないということです。は同期的ですが、結果reducer
の完了が保証されるという保証はないようです。この多くは では異なりますが、少なくとも で話している場合は.dispatch
reducer
redux
React
17.0.2
テスト ケースの例を次に示します。
import { useReducer } from "react";
import "./styles.css";
function reducer(state, action) {
console.log("REDUCER", state, action);
switch (action.type) {
case "INCREMENT":
return state + 1;
default:
return state;
}
}
export default function App() {
const [state, dispatch] = useReducer(reducer, 0);
const myDispatch = function (...args) {
console.log("dispatched", args);
return dispatch(...args);
};
const onClick = function () {
// BOTH dispatches fired before any reducer!
myDispatch({ type: "INCREMENT" });
myDispatch({ type: "INCREMENT" });
};
const onClickAsync = async function () {
// reducer finishes before next dispatch called
await myDispatch({ type: "INCREMENT" });
await myDispatch({ type: "INCREMENT" });
};
return (
<>
<pre>{state}</pre>
<button onClick={onClick}>Increment Broken</button>
<button onClick={onClickAsync}>Increment Working</button>
</>
);
}
サンドボックス: https://codesandbox.io/s/dispatch-not-sync-db9wn?file=/src/App.tsx
その例では、Increment Broken
ボタンをクリックするとディスパッチが次々に実行され、リデューサー呼び出しの前に両方のディスパッチのログ ステートメントが表示されることがコンソールに表示されます。
一方、Increment Working
ボタンをクリックすると、ディスパッチ -> レデューサー -> ディスパッチ -> レデューサーが正しく行われることがわかります。
レデューサーの実行は、キューに入れられた順序であることが保証され、2 番目のレデューサーによって受信された状態は、実際には前のレデューサーの状態です。したがって、基本的にこれは、2 番目のディスパッチのキューイングが、次のディスパッチを開始する前に完了するレデューサーに依存する場合にのみ重要です。