10

从链接引用。 https://react-redux.js.org/next/api/hooks#performance

我理解useSelector钩子的好处是避免包装地狱。由于HOC的使用,包装地狱正在发生。如果由于性能原因我们必须使用HOC,那么简单地使用HOC会更好吗?因为在任何情况下,我们都将陷入wrappers 的地狱。如果地狱不是那么将是。connect React.memo useSelectorconnect connectReact.memo

请任何人解释React.memoover的好处connect

4

3 回答 3

22

好吧,首先,虽然 React.memo 是一个 HOC,但它并没有像 connect 那样创建相同的嵌套,这很有趣。我创建了一个测试代码:

    import React from "react";
    import ReactDOM from "react-dom";
    import {connect, Provider} from 'react-redux'
    import { createStore } from 'redux'
    import "./styles.css";
    
    const MemoComponent = React.memo(function MyMemo() {
      return <div>Memo</div>;
    });
    
    const ConnectedComponent = connect(null,null)(function MyConnected() {
      return <div>ReduxConnectComponent</div>;
    })
    
    const store = createStore(()=>{},{})
    
    
    function App() {
      return (
        <Provider store={store}>
          <MemoComponent />
          <ConnectedComponent/>
        </Provider>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);

这是呈现的结构:

在此处输入图像描述

我们可以看到 connect 的内容被渲染得更深了。

其次,文档说:

默认情况下,使用useelector()将在派遣操作后运行选择器函数时对选定值进行参考平等比较,并且如果所选值更改,则只会导致组件重新渲染。但是,与 connect() 不同的是,useSelector() 不会由于其父级重新渲染而阻止组件重新渲染,即使组件的 props 没有更改。

这意味着当 store 的不相关部分发生变化时,不会重新渲染 useSelector 的组件。这是优化中最重要的部分。现在是否使用 React.memo 进行优化完全取决于您的决定,并且在大多数情况下,根本不需要它。我们仅在组件渲染成本非常高的情况下使用 React.memo。

总而言之,需要连接包装器才能连接到商店。有了 useSelector,我们就不必再包装了。在极少数情况下,当我们需要优化一些繁重的组件时,我们仍然需要使用 React.memo 进行包装。React.memo 的工作也是由 connect 完成的,但在大多数情况下,这是过早的优化。

于 2019-06-12T06:30:09.667 回答
2

我一直试图得到一个答案很长一段时间,但我得到的答案并不清楚。虽然 Redux 文档中的理论并不复杂:useSelector使用严格相等===,而 connect 使用浅相等来确定。因此,在这两种情况下,如果您从 Redux 状态(数字、字符串、布尔值)“拉取”一个原始值,您将得到相同的结果。如果值未更改,则任何组件都不会重新呈现。如果您正在“拉取”非基元(数组或对象)并且两种情况下的值都没有改变(useSelector、connect),那么使用的组件useSelector仍然会重新渲染,因为它们当然[] === []总是错误的,因为它们正在引用不同的数组,其中connected 组件不会重新渲染。现在为了使useSelector行为相似且不重新渲染,您可以这样做: const object = useSelector(state => state.object, shallowEqual)您可以shallowEqualreact-redux. 或者通过使用reselect库来使用该状态的记忆版本:

const makeGetObject = () => createSelector(state => state.object, object => object)

并将其添加到您的选择器中,例如:const object = useSelector(state => state.object, makeGetObject);当我试图了解它的底部时,我已经创建了这个代码框(检查WithUseSelector组件中的注释):useSelector vs connect()

于 2020-05-21T15:43:51.593 回答
0

我只是定制了 useSelector 钩子来避免这种情况,而且效果很好

import { useSelector, useDispatch } from 'react-redux'
import { _lodash } from '../../../lodash'

export const useCloneSelector = (selector = (obj) => obj) => {
  const selectWithClonedState = (state = {}, ...others) => selector(_lodash.cloneDeep(state), ...others)
  return useSelector(selectWithClonedState, _lodash.isEqual)
}

export { useDispatch, useSelector }

于 2021-12-07T14:47:17.500 回答