如何用createSelector()记忆useElector()?

发布于 2025-01-21 12:03:41 字数 1533 浏览 2 评论 0 原文

我想在我的编程网站上解释redux商店的回忆。

我现在拥有的

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()记忆。我不明白那个库。有人可以提供一些指导吗?

参考:

  1. 使用记忆的选择器 2)'Reselect'库

I wish to explain the memoization on a Redux store on my programming website.

What I have now on 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>
  );
};

As you can see, I have successfully memorized the dispatch() function with useCallback(). However, every time the button is clicked, useSelector() is called twice.

Is there a way to call it once only? I am thinking about memorization with createSelector() from the 'reselect' library. I don't understand that library. Could someone provide some guidance?

References:

  1. Using memorizing selectors 2) The 'reselect' library

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

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

发布评论

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

评论(1

久夏青 2025-01-28 12:03:41

他们通过将选择器运行2次来正常工作。如果您还将选择器内部的状态(计数器)打印出来,将会更容易,更明显。

参考: https://reaect-react-react-react-react-react-react.js.ss.org/ API/钩子#Equality-Comparisons and-updates

事情将是这种方式:

  1. 在UI上呈现一个按钮和0。
  2. 您单击按钮,该按钮可以派遣操作。
  3. 选择器首次运行时,它看到了派遣动作,它检测到返回值的变化,因此迫使组件重新渲染。日志用新值(不是旧值)打印出来。

但是,当操作被派遣到Redux Store时,使用Elector()仅在选择器结果似乎与最后结果不同的情况下强制重新渲染。从v7.1.0-alpha.5开始,默认比较是严格的===参考比较。这与Connect()不同,Connect()使用MapState调用的结果浅层平等检查来确定是否需要重新渲染。这对您应该如何使用useselector()

有几种影响

  1. 组件重新租用器有几种含义,这触发了第二个日志(“渲染...”)。
  2. 这也导致选择器的重新运行,这解释了第三log。

当函数组件渲染时,将调用提供的选择器函数,并将其结果从useElector()挂钩返回。 (如果选择器的功能与组件的先前渲染相同,则可以通过钩子返回缓存结果,而无需重新运行选择器。)

They are working correctly by having running the selectors 2 times. It would be easier and more obvious if you also print out the state (the counter) inside the selector.

Reference: https://react-redux.js.org/api/hooks#equality-comparisons-and-updates

Things will be this way:

  1. A button and 0 are rendered on the UI.
  2. You click the button, which dispatches an action.
  3. The selector runs for the first time as it sees an action dispatched, it detects a change in the returned value, so it forces the component to re-render. Log is printed out with the NEW value (not the OLD one).

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()

  1. The component re-renders, which triggers the the second log ("rendering ...").
  2. That also leads to a re-run of the selector, which explains the third log.

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.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文