如何使Memoization与UseCallback()和Redux-toolkit createSelector()一起使用?

发布于 2025-02-05 07:20:03 字数 1578 浏览 3 评论 0原文

根据此处的文档

创建唯一的选择器实例:

在许多情况下,需要在多个组件中重复使用选择器函数。如果组件都将所有参数都调用选择器,则它将打破记忆 - 选择器永远不会多次看到相同的参数,因此永远无法返回缓存的值。

这里的标准方法是在组件中创建一个记忆的选择器的唯一实例,然后将其与useElector一起使用。这允许每个组件始终如一地将相同的参数传递给其自己的选择器实例,并且选择器可以正确记忆结果。

对于功能组件,通常是使用USEMEMO或USECALLBACK完成的:

当我做 codesandbox上的以下内容

import { useCallback } from "react";
import { useSelector, useDispatch } from "react-redux";
import { increment, selectSum } from "./reducer";

function Sum({ value }) {
  const selectSumMemoized = useCallback(selectSum, []);
  const sum = useSelector((state) => selectSumMemoized(state, value));
  return (
    <div>
      sum: {sum} (10+100+{value})
    </div>
  );
}

export default () => {
  const dispatch = useDispatch();
  return (
    <div>
      <Sum value={1} />
      <Sum value={2} />
      <button onClick={() => dispatch(increment())}>
        change state and re-render
      </button>
    </div>
  );
};

当我通过重复单击按钮启动重新渲染时,SelectSum登录的输出选择器两次,暗示Memoization不是跨多个组件工作。

我需要做出什么更改才能正常工作?

According to the documentation here:

Creating Unique Selector Instances:

There are many cases where a selector function needs to be reused across multiple components. If the components will all be calling the selector with different arguments, it will break memoization - the selector never sees the same arguments multiple times in a row, and thus can never return a cached value.

The standard approach here is to create a unique instance of a memoized selector in the component, and then use that with useSelector. That allows each component to consistently pass the same arguments to its own selector instance, and that selector can correctly memoize the results.

For function components, this is normally done with useMemo or useCallback:

When I did the following on codesandbox:

import { useCallback } from "react";
import { useSelector, useDispatch } from "react-redux";
import { increment, selectSum } from "./reducer";

function Sum({ value }) {
  const selectSumMemoized = useCallback(selectSum, []);
  const sum = useSelector((state) => selectSumMemoized(state, value));
  return (
    <div>
      sum: {sum} (10+100+{value})
    </div>
  );
}

export default () => {
  const dispatch = useDispatch();
  return (
    <div>
      <Sum value={1} />
      <Sum value={2} />
      <button onClick={() => dispatch(increment())}>
        change state and re-render
      </button>
    </div>
  );
};

as I initiated a re-render by clicking the button repeatedly, the output selector of selectSum logged twice, implying that memoization is not working across multiple components.

What changes do I need to make for it to work correctly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

七堇年 2025-02-12 07:20:03

我发现了。

基本上,我需要定义和使用以下功能(只需add()=&gt;):

const makeSelectSum = () =>
  createSelector([select100, select10, (state, n) => n], (a, b, num) => {
    console.log("output selector called: " + num);
    return a + b + num;
  });

然后:

const selectSumMemo = useMemo(makeSelectSum, []);
const sum = useSelector((state) => selectSumMemo(state, value));

或:

const selectSumMemo = useCallback(makeSelectSum(), []);
const sum = useSelector((state) => selectSumMemo(state, value));

而不是直接使用此功能:

const selectSum =
  createSelector([select100, select10, (state, n) => n], (a, b, num) => {
    console.log("output selector called: " + num);
    return a + b + num;
  });

I figured it out.

Basically, I need to define and use the following function (just add ()=>):

const makeSelectSum = () =>
  createSelector([select100, select10, (state, n) => n], (a, b, num) => {
    console.log("output selector called: " + num);
    return a + b + num;
  });

Then:

const selectSumMemo = useMemo(makeSelectSum, []);
const sum = useSelector((state) => selectSumMemo(state, value));

or:

const selectSumMemo = useCallback(makeSelectSum(), []);
const sum = useSelector((state) => selectSumMemo(state, value));

instead of using this one directly:

const selectSum =
  createSelector([select100, select10, (state, n) => n], (a, b, num) => {
    console.log("output selector called: " + num);
    return a + b + num;
  });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文