Refreshing children state from parent React

Tomasz Kasperek picture Tomasz Kasperek · Apr 24, 2015 · Viewed 25.8k times · Source

I have a table with some data and each element in the table is a React class component. It looks like this:

Table

All i want is to have one checkbox for "check all" feature (top left checkbox). The thing is I don't know how to solve that because of props and state.

I have code like that in single element component:

getInitialState: function() {
    return { component: this.props.data };
  },

render: function() {
    var data = this.state.component;
    data = data.set('checked', this.props.data.get('checked'));
    ...
}

And I know I shouldn't get checked param from props but it is just temporary.

What I have problem with is: When I update checked param in parent it doesn't update state, because getInitialState isn't called after refresh (yep, i know it should be like that).

My question is: can I somehow update state of child component? Or it is better way to achieve that.

Answer

Samuli Hakoniemi picture Samuli Hakoniemi · Apr 24, 2015

My approach is that you should have structure something like this in parent's render:

<ParentView>
{ this.props.rows.map(function(row) {
    <ChildRow props={row.props} />
  }).bind(this)
}
</ParentView>

And then on row.props you have the information whether current row item is checked or not. When parent checkbox is toggled, you populate all the row.props with the status.

On child, you will receive those with componentWillReceiveProps and you do the magic (e.g. set the correct state) when checkbox is toggled:

componentWillReceiveProps: function(props) {
  this.setState({isChecked: props.isChecked});
}

(Info from the React's docs: Calling this.setState() within this function will not trigger an additional render.)

Child element's render would be something like:

<div>
  <input type='checkbox' checked={this.state.isChecked} />
  <label>{this.props.label}</label>
</div>