我如何使用 ES6 在 React 组件中保持状态

IT技术 javascript reactjs
2021-05-10 23:16:15

我正在尝试在 ES6 中使用有状态的 React 组件,但是当我定义构造函数时,构造函数只会在多次渲染组件(从其父级)时调用一次。示例如下所示。

class SubComponent extends React.Component {
  constructor(props) {
    super(props);
    console.log("Creating sub component");
    this.state = { count: props.count };
  }

  render() {
    console.log("Rendering sub component", this.state.count);
    return (<div>count: {this.state.count}</div>);
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    console.log("Creating app");
    this.state = { count: 0 };
    this.tick = this.tick.bind(this);
    setInterval(this.tick, 1000);
  }

  tick() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    console.log("Rendering app", this.state.count);
    return (<SubComponent count={this.state.count} />);
  }
}

这不会更新呈现的输出(它将始终是count: 0),但日志将输出:

Creating app
Rendering app 0
Creating sub component
Rendering sub component 0
Rendering app 1
Rendering sub component 0
Rendering app 2
Rendering sub component 0
Rendering app 3
Rendering sub component 0
...

这是一个 JSFiddle:http : //jsfiddle.net/jor0xu1a/1/

我知道该示例SubComponent不需要状态,但我尝试使其尽可能简单以显示我的问题。

我错过了什么?

4个回答

在子组件中它props不是状态 - 将其更改为this.props.count,这将起作用

我建议阅读getInitialState Is an Anti-Pattern 中的props

基本上,尽可能少的组件应该有状态。正如其他答案已经说过的那样,在您的情况下,您可以使用this.props.count来引用当前值。似乎没有任何理由SubComponent应该拥有自己的状态。

然而,如果你真的想从它接收到的 props 计算组件的状态,你有责任使用生命周期方法使它们保持同步componentWillReceiveProps

componentWillReceiveProps(nextProps) {
    this.setState({count: nextProps.count});
}

你的子组件应该是:

 class SubComponent extends React.Component {
      constructor(props) {
        super(props);
        console.log("Creating sub component");
      }

      render() {
        return (<div>count: {this.props.count}</div>);
      }
    }

我的不好,我认为getInitialState每当父组件重新渲染组件时都会调用构造函数(或用于 ES5)(我认为父组件在渲染时“重新创建”了它的子组件),但情况并非总是如此。我应该先阅读它 ( url ) 并使用 ES5 ( jsFiddle )尝试它,然后再认为这是我用 ES6 不理解的东西并在这里创建一个问题。

是的,该示例SubComponent应该使用,this.props但我的用例在我的真实组件中具有实际的有状态功能。我创建了这个示例,因为我出于某种原因认为结果不是使用 ES6 时的预期结果(但确实如此)。

感谢您的反馈!