Karl Thunberg
Karl Thunberg

Reputation: 91

How can i keep state in a React component using ES6

I'm trying to use a stateful React component with ES6 but when I define a constructor the constructor will only be called once while the component is rendered multiple times (from its parent). Example shown below.

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

This will not update the rendered output (it will always be count: 0) but the logs will output:

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
...

Here's a JSFiddle: http://jsfiddle.net/jor0xu1a/1/

I'm aware that the example SubComponent doesn't need a state but I tried making it as simple as possible to show my problem.

What am I missing?

Upvotes: 0

Views: 638

Answers (4)

Karl Thunberg
Karl Thunberg

Reputation: 91

My bad, I thought that the constructor (or getInitialState for ES5) is called whenever the component is being re-rendered by the parent (I thought that the parent 're-creates' its children on render) but that's not always the case. I should had read up on it (url) and tried it with ES5 (jsFiddle) before thinking it was something I didn't understand with ES6 and creating a question here.

And yes, the example SubComponent should use this.props but my use case had actual stateful functionality in my real component. I created the example as I thought for some reason that the result weren't the expected outcome when using ES6 (but it was).

Thank you for you feedback!

Upvotes: 0

Felix Kling
Felix Kling

Reputation: 816394

I recommend to read Props in getInitialState Is an Anti-Pattern.

Basically, as few components as possible should have state. As the other answers already said, in your case you can just use this.props.count to refer to the current value. There doesn't seem to be any reason why SubComponent should have its own state.

However, if you really want to compute the component's state from the props it receives, it is your responsibility to keep them in sync, with the life cycle method componentWillReceiveProps:

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

Upvotes: 2

Florim Maxhuni
Florim Maxhuni

Reputation: 1421

You SubComponent should be:

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

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

Upvotes: 0

Isla
Isla

Reputation: 2462

In SubComponent it is props not state - change it to this.props.count and this will work

Upvotes: 3

Related Questions