Redux mapStateToProps多次调用

ang*_*ner 6 reactjs redux react-redux

我有这个非常简单的Component,它连接到redux状态并返回{fruit, vegetables}.一切正常,但是假设我在Component中有一个图表,如果仅从vegetableAPI 更新,则每次都会重新创建图表.

这是我的组件:

const Products = ({ fruit, vegetable }) =>
  <div className='Products'>
      <div>{vegetable.map(....logic here)}</div>
      <div>{Math.random()}</div> // this is to illustrate the component is rendering every time
      <Graph>Here will be a chart or a graph with fruit</Graph> //but it gets re-rendered even though there is no new fruit
  </div>

const mapStateToProps = (state) => {
  return {
    fruit: state.data.fruit,
    vegetable:  state.data.vegetable,
  }
}

export default connect(mapStateToProps)(Products)
Run Code Online (Sandbox Code Playgroud)

在我看来,无论哪个状态更新,它都会重新呈现整个组件.

有办法防止这种情况吗?

Von*_*onD 6

当React组件被渲染时,它下面的整个组件树也被渲染-除了shouldComponentUpdatehook返回的组件之外false。因此,在您的情况下,如果Products组件被渲染,则Graph组件也会正常显示。

您在这里有两个选择:

  • 如果您的Products组件未使用组件fruit外部的prop,则Graph可以将Graph组件直接连接到fruit状态,并使用函数的pure选项connect来避免在fruit未更改时重新渲染

  • 您可以shouldComponentUpdateGraph组件中定义钩子,以手动跳过不必要的渲染,或使用帮助程序库为您完成此操作,例如库的pure帮助程序recompose

第一个选项通常是开始优化react / redux应用程序/避免不必要的渲染:将组件连接到最有意义的最低层。第二个选项更多是逃生舱口-但仍然经常有用。

正如您提到的使用无状态组件一样,您可以使用更高阶的组件来从shouldComponentUpdate钩子中受益。要了解它是如何工作的,下面是它的简单实现如下所示:

function pure(BaseComponent, shouldUpdateFn) {
    return class extends Component {
        shouldComponentUpdate(nextProps) {
            return shouldUpdateFn(this.props, nextProps);
        }
        render() {
            return <BaseComponent { ...this.props } />;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个pureHOC,您可以在应用程序上重用它以避免不必要的渲染:它通过将无状态组件包装到具有所需钩子的新组件中来工作。您将像这样使用它,例如:

export default pure(Graph, (props, nextProps) => props.fruit !== nextProps.fruit)
Run Code Online (Sandbox Code Playgroud)

尽管如此,我还是强烈建议您研究一下recompose,它具有更细粒度的实现,并且可以避免您重新发明轮子。