基于全局状态变化重新渲染单个子组件,无需重新渲染兄弟组件

Dav*_*oty 3 reactjs

我有一个带有许多子组件的 React 父组件(成千上万的 SVG 元素重新渲染起来很昂贵)。子组件基于全局状态显示信息;某处是应该以特殊方式显示的那些子组件的列表。由于其他地方需要此列表,因此它不能是每个孩子的本地状态信息,因为它不是孩子的私有信息。

按照这里的建议:https : //reactjs.org/docs/lifting-state-up.html我将状态提升到父组件。然而,一次只有一个孩子会改变;例如,用户可能会单击一个 SVG 元素来调整其显示属性(这些属性存储为孩子的道具)。但是,由于状态存储在父组件中,因此调用setState父组件会触发整个父组件(包括其所有数千个子组件)的昂贵重新渲染,即使它们中的大多数没有更改。

所以我不确定如何在 React 中正确地做到这一点并获得良好的性能。(我找到了这个forceUpdate方法,还有很多警告永远不要使用它。)我想我想做的是以某种方式更新孩子的道具,但从文档中,我可以看到父母的唯一方法更新单个孩子的道具,是为了render()调用父级的方法,这意味着它也在重新渲染所有没有改变的兄弟姐妹,这是我想要避免的昂贵情况。

有没有办法让存储在父级或其他地方的点击处理程序可以访问全局状态,来改变这个状态,并更新它影响的单个子组件的道具,然后只告诉那个子组件重新 -使成为?

抱歉,我没有包含任何源代码;这实际上是用 Dart 编写的,而不是 JS,但我认为问题出在底层 React 库的级别。

Tia*_*ves 5

您必须使用shouldComponentUpdate(), React.PureComponentor React.memo()(如果您使用的是 React > v16.6.0 和功能组件)。你想要这样的东西:

父组件

class Parent extends Component {
  state = {
    color1: "red",
    color2: "blue"
  };

  changeState = () =>
    this.setState((state, props) => ({
      color1: state.color1 === "red" ? "yellow" : "red",
      color2: state.color2
    }));

  render() {
    return (
      <>
        <Child color={this.state.color1} />
        <Child color={this.state.color2} />
        <button onClick={this.changeState}>Change State</button>
      </>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

color1每次Change State单击时,父级都会在红色和黄色之间切换状态属性。然后,您有一些选项可以优化您的应用程序。

应该组件更新()

class Child extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.color !== this.props.color) return true;
    return false;
  }
  render() {
    return (
      <div style={{ backgroundColor: this.props.color }}>I am a child</div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

React.PureComponent

class PureComponentChild extends React.PureComponent {
  render() {
    return (
      <div style={{ backgroundColor: this.props.color }}>I am a child</div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

React.memo()

const FunctionalChild = React.memo(props =>
  <div style={{ backgroundColor: props.color }}>I am a child</div>
);
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看shouldComponentUpdate()React.PureComponentReact.memo()