Guifan Li Guifan Li - 6 months ago 26
Javascript Question

react lifecycle methods understanding

I am a newbie to React.js and I am trying hard to understand several methods in react lifecycle methods.

So far, I still have something that confuses me:

1)

As far as my understanding, the difference between

componentWillUpdate
and
componentWillReceiveProps

is that
componentWillReceiveProps
will called when parent change the props and we can use setState (setState of this child inside
componentWillReceiveProps
).

for example:
https://github.com/bgerm/react-table-sorter-demo/blob/master/jsx/app.jsx

var App = React.createClass({
getInitialState: function() {
return {source: {limit: "200", source: "source1"}};
},
handleSourceChange: function(source) {
this.setState({source: source});
},
render: function() {
return (
<div>
<DataSourceSelectors onSourceChange={this.handleSourceChange} source={this.state.source} />
<TableSorter dataSource={urlForDataSource(this.state.source)} config={CONFIG} headerRepeat="5" />
</div>
);
}
});


In TableSorter, we have

componentWillReceiveProps: function(nextProps) {
// Load new data when the dataSource property changes.
if (nextProps.dataSource != this.props.dataSource) {
this.loadData(nextProps.dataSource);
}
}


meaning when we change
this.state.source
, we will expect
componentWillReceiveProps
be called in TableSorter

However, I don't quite understand how to use
componentWillUpdate
in this case, the definition of
componentWillUpdate
is

componentWillUpdate(object nextProps, object nextState)


How can we pass nextState from parent into child? Or maybe I am wrong, is the nextState passed from the parent element ?

2)
method
componentWillMount
confuses me because in the official document, it says that


Invoked once, both on the client and server, immediately before the
initial rendering occurs.


In this case, if I use setState in this method, it will overrides the getInitialState since it will called once only on initial. In this case, what the reason to set the parameters in the getInitialState method. In this particular case, we have

getInitialState: function() {
return {
items: this.props.initialItems || [],
sort: this.props.config.sort || { column: "", order: "" },
columns: this.props.config.columns
};
},
componentWillMount: function() {
this.loadData(this.props.dataSource);
},
loadData: function(dataSource) {
if (!dataSource) return;

$.get(dataSource).done(function(data) {
console.log("Received data");
this.setState({items: data});
}.bind(this)).fail(function(error, a, b) {
console.log("Error loading JSON");
});
},


items will be overrode initially and why we still need
items: this.props.initialItems || []
int the getInitialState method?

Hope you can understand my explanation, and please give me some hints if you have any. Many thanks for that :)

Answer

1) componentWillReceiveProps is called before componentWillUpdate in React's update lifecycle. You are right that componentWillReceiveProps allows to call setState. On the other hand componentWillUpdate is a callback to use when you need to response to a state change.

The fundamental difference between props and state that state is a private to the component. That's why parent component or anybody else cannot manipulate the state (e.g. call setState) of the component. So the default workflow for the parent-child components relationship would be the following:

  • Parent passes new props to the child
  • Child handles new props in 'componentWillReceiveProps', calls setState if necessary
  • Child handles new state in 'componentWillUpdate', but if your component is statefull, handling props in 'componentWillReceiveProps' will be enough.

2) You provided quite a good code example to illustrate the difference. Default values set in getInitialState will be used for initial rendering. loadData call from componentWillMount will initiate AJAX request which may or may not succeed, moreover it is unknown how long it will take to complete. By the time AJAX request completes and setState will be called with new state, the component will be rendered in DOM with default values. That is why it makes total sense to provide default state in getInitialState.

Note: I found Understanding the React Component Lifecycle article a huge help for the understanding of React's lifecycle methods.

Comments