如何使用 createSelector() 来记忆 useSelector()?
我希望在 我的编程网站 上解释 Redux 存储的记忆化。
我现在在 CodeSandbox 上拥有:
import { useCallback, useMemo, memo } from "react";
import { useSelector, useDispatch } from "react-redux";
import { createSelector } from "reselect";
const Plus = memo(({ onIncrement }) => {
console.log("rendering <Plus>...");
return <button onClick={onIncrement}>+</button>;
});
export default () => {
console.log("rendering <App>...");
const v = useSelector((state) => {
console.log("useSelector() invoked");
return state;
});
const dispatch = useDispatch();
const increment = useCallback(() => dispatch({ type: "INCREMENT" }), [
dispatch
]);
return (
<div>
<span>{v}</span>
<Plus onIncrement={increment} />
</div>
);
};
如您所见,我已使用 useCallback() 成功记忆了 dispatch() 函数。但是,每次单击按钮时,都会调用 useSelector() 两次。
有没有办法只调用一次?我正在考虑使用“reselect”库中的 createSelector() 进行记忆。我不了解那个库。有人能提供一些指导吗?
参考:
通过运行选择器 2 次,它们可以正常工作。如果您还打印出选择器内的状态(计数器),则会更容易、更明显。
参考: https://react-redux.js.org/api/hooks#equality-comparisons-and-updates
事情会是这样的:
- 在 UI 上呈现一个按钮和 0。
- 您单击按钮,它会分派一个操作。
- 选择器在看到分派的操作时首次运行,它会检测到返回值的变化,因此它会强制组件重新渲染。日志打印出新值(而不是旧值)。
However, when an action is dispatched to the Redux store, useSelector() only forces a re-render if the selector result appears to be different than the last result. As of v7.1.0-alpha.5, the default comparison is a strict === reference comparison. This is different than connect(), which uses shallow equality checks on the results of mapState calls to determine if re-rendering is needed. This has several implications on how you should use useSelector()
- 组件重新渲染,触发第二条日志(“渲染...”)。
- 这也导致选择器重新运行,从而解释第三条日志。
When the function component renders, the provided selector function will be called and its result will be returned from the useSelector() hook. (A cached result may be returned by the hook without re-running the selector if it's the same function reference as on a previous render of the component.)