【问题标题】:How to use React.memo with react-redux connect?如何将 React.memo 与 react-redux 连接一起使用?
【发布时间】:2018-10-25 21:37:46
【问题描述】:

有人知道在使用 react-redux 中的 connect 函数时如何用 React.memo 包装 React 组件吗?

例如,您将如何修改以下内容?

let Button = (props: Props) => (
  <button onClick={props.click}>{props.value}</button>
);

Button = connect(
  mapStateToProps,
  mapDispatchToProps
)(Button);

我试过了:

let Button = React.memo((props: Props) => (
  <button onClick={props.click}>{props.value}</button>
));

Button = connect(
  mapStateToProps,
  mapDispatchToProps
)(Button);

但是,connect 返回的函数需要传递一个组件,因此它会出错:

未捕获的错误:您必须将组件传递给由返回的函数 连接。而是收到 {"compare":null}

【问题讨论】:

  • React.memo(connect(...)(Button)) 呢?
  • @putvande 是的,这段代码可以,但是memo的第二个参数获取不到mapStateToProps返回的对象……

标签: javascript reactjs redux connect


【解决方案1】:

React.memo 只是一个 HOC,所以你可以使用:

无备注:

connect(
  mapStateToProps,
  mapDispatchToProps
)(Button);

附备忘录:

connect(
  mapStateToProps,
  mapDispatchToProps
)(React.memo(Button));

甚至换行连接:(这应该是连接的解决方案)

React.memo(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(Button)
);

就像我们对withRouter 所做的那样:withRouter(connect(...)())

【讨论】:

  • 你为什么说最后一个解决方案应该是正确的?对我来说,React.memo 似乎应该是最接近组件本身的 HOC,因为它应该是接收存储并检查是否需要重新渲染的 HOC,而在最后一个解决方案中,它只检查使用直接传递给组件而不是商店的道具重新渲染。
  • 但是,如果该组件使用 Redux 属性(而不是父级继承的属性),你是否应该在连接 Redux 组件时使用 memo?可能不会,因为 Redux 已经自动进行了浅层比较。
  • @arnaudambro,我认为在connect 内部或外部使用memo 取决于具体情况。 Redux 的 connect 有自己的选项来确定从 store 创建的 props 的相等性,因此您可以在外部使用 React.memo 对直接 props 使用其相等性检查,并依赖 connect 选项进行相等性检查store 道具。如果 React.memo 的相等性检查适用于直接道具和商店道具,那么将其放在 connect 中是有意义的
【解决方案2】:

这里也是同样的问题。通过将react-redux 升级到版本 5.1.0 修复。

【讨论】:

  • 那么connect( mapStateToProps, mapDispatchToProps )(React.memo(Button));let Button = React.memo((props: Props) =&gt; ( &lt;button onClick={props.click}&gt;{props.value}&lt;/button&gt; )); 哪种格式更高效,或者没有真正的区别?
  • @Ryc 你不想在连接的组件上使用 memo:给组件的 props 不会改变,而 redux 状态可能会改变并需要更新......
【解决方案3】:

您的解决方案应该可以工作(我没有尝试那样复制粘贴),但您还必须将 react-redux 更新到最新版本。

顺便说一句,我认为React.memo 在许多 HOC 中的正确实现是最接近组件本身:React.memo 的目标是检查组件接收到的所有新道具是否都是和上一个道具一样。如果任何 HOC 转换或添加任何 props 到组件 - connect 通过将 Redux 存储映射到 props 来实现,React.memo 应该知道它以便决定是否更新组件。

所以我会去做这样的事情:

//import what you need to import

const Component = props => <div>{/* do what you need to do here */}</div>

export default compose(
  connect(mapStateToProps, dispatchToProps),
  /* any other HOC*/
  React.memo
)(Component);

【讨论】:

    【解决方案4】:

    Codesandbox demo

    正如错误消息所说,您需要将一个组件传递给来自connect 的返回函数。
    (这意味着connect()() 中的第二对())

    React.Memo 返回一个组件时,将它传递给connect 的第二个函数。
    您可以这样做。

    export const MemoizedDemoComponent = connect(mapStateToProps)(React.memo(DemoComponent);
    

    演示组件:

    import React from "react";
    import { connect } from "react-redux";
    
    const DemoComponent = props => (
      <div>
        <p>My demo component fueled by: {props.fuel}!</p>
        <p>Redux: {props.state}</p>
      </div>
    );
    
    const mapStateToProps = state => ({
      state: "your redux state..."
    });
    
    // create a version that only renders on prop changes
    export const MemoizedDemoComponent = connect(mapStateToProps)(
      React.memo(DemoComponent)
    );
    

    对于一个工作示例,请检查codesandbox

    【讨论】:

      【解决方案5】:

      对于想知道为什么react-redux 抛出此错误的人。

      对我来说,我使用版本5.0.7react-redux/src/components/connectAdvanced.js line: 92

      invariant(
        typeof WrappedComponent == 'function',
        `You must pass a component to the function returned by ` +
        `${methodName}. Instead received ${JSON.stringify(WrappedComponent)}`
      );
      

      升级后这段代码改为:

      invariant(
        isValidElementType(WrappedComponent),
        `You must pass a component to the function returned by ` +
        `${methodName}. Instead received ${JSON.stringify(WrappedComponent)}`
      );
      

      如何查看WrappedComponent改成isValidElementType(WrappedComponent)react-is暴露的@

      所以,yarn 至少将react-redux 更新到@Maxime Chéramy 提到的版本

      【讨论】:

        猜你喜欢
        • 2020-06-21
        • 2021-01-07
        • 1970-01-01
        • 1970-01-01
        • 2019-02-20
        • 2016-08-11
        • 2020-01-06
        • 2021-07-07
        • 1970-01-01
        相关资源
        最近更新 更多