简体   繁体   English

如何通过 react-redux 连接使用 React.memo?

[英]How to use React.memo with react-redux connect?

Does anyone know how to wrap a React component with React.memo when one is using the connect function from react-redux?有谁知道当使用来自 react-redux 的connect function 时如何用React.memo包装 React 组件?

For example, how would you modify the following?例如,您将如何修改以下内容?

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

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

I've tried:我试过了:

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

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

However, the function returned by connect expects a component to be passed so it errors with:但是, connect返回的 function 需要传递一个组件,因此它会出错:

Uncaught Error: You must pass a component to the function returned by connect.未捕获的错误:您必须将组件传递给连接返回的 function。 Instead received {"compare":null}而是收到 {"compare":null}

React.memo is nothing but a HOC, so you can just use: React.memo只是一个HOC,所以你可以使用:

Without memo: 没有备忘录:

connect(
  mapStateToProps,
  mapDispatchToProps
)(Button);

With memo: 备忘录:

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

And even wrap to connect: (This should be the solution with connect) 甚至包装连接:(这应该是连接的解决方案)

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

Like we do with withRouter : withRouter(connect(...)()) 就像我们使用withRouterwithRouter(connect(...)())

Same issue here. 同样的问题在这里 Fixed by upgrading react-redux to version 5.1.0. 通过将react-redux升级到版本5.1.0来修复。

Your solution should work (I didn't try copy-pasted like that), but you also have to update react-redux to the latest version. 您的解决方案应该可以工作(我没有尝试像这样复制粘贴),但您还必须将react-redux更新到最新版本。

By the way, I think the proper implementation of React.memo within many HOC would be to be the closest to the component itself : the goal of React.memo is to check if all the new props received by the component are the same as the last props. 顺便说一句,我认为在许多HOC中React.memo的正确实现将是最接近组件本身: React.memo的目标是检查组件接收的所有新道具是否与最后的道具。 If any HOC transforms or adds any props to the component - which connect does by mapping the Redux store to the props, React.memo should be aware of it in order to decide wether or not to update the component. 如果任何HOC转换或添加任何道具到组件 - connect通过将Redux存储映射到道具, React.memo应该知道它以决定更新或不更新组件。

So I would go for something like that : 所以我会选择这样的东西:

//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);

Codesandbox demo Codesandbox演示

As the error message says, you need to pass a component to the returned function from connect . 如错误消息所示,您需要将组件从connect传递给返回的函数。
( which means the second pair of () in connect()() ) (表示connect()()的第二对connect()()

As React.Memo returns a component, pass it into the second function of connect . React.Memo返回一个组件时,将其传递给connect的第二个函数。
Here's how you can do this. 这是你如何做到这一点。

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

Demo component: 演示组件:

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

For a working example check also codesandbox . 对于工作示例,还要检查codesandbox

For someone who want to know why react-redux throw this error.对于想知道为什么react-redux抛出此错误的人。

For me, I used version 5.0.7 , react-redux/src/components/connectAdvanced.js line: 92对我来说,我使用了5.0.7版本, react-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)}`
);

After upgrading this code is changed to:升级后此代码更改为:

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

How to check the WrappedComponent is changed to isValidElementType(WrappedComponent) which is exposed by react-is如何检查WrappedComponent是否更改为isValidElementType(WrappedComponent) ,它由react-is公开

So, yarn update react-redux to the version that mentioned by @Maxime Chéramy at least因此,纱线至少将 react-redux 更新为@Maxime react-redux提到的版本

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM