Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS state vs prop

Tags:

reactjs

Updating 2016: React is changed, and explanation "props vs state" became very simple. If a component needs to change data - put it in a state, otherwise in props. Because props are read-only now.

What's the exact difference between props and state?

You can find good explanation here (full version)

Changing props and state


Your second approach is more like it. React doesn't care about models so much as it cares about values and how they flow through your app. Ideally, your post model would be stored in a single component at the root. You then create child components that each consume parts of the model.

You can pass callbacks down to the children that need to modify your data, and call them from the child component.

Modifying this.props or this.state directly is not a good idea, because React will not be able to pick up on the changes. That's because React does a shallow comparison of your post prop to determine if it has changed.

I made this jsfiddle to show how data could flow from an outer to an inner component.

The handleClick method shows 3 ways to (im)properly update state:

var Outer = React.createClass({

  getInitialState: function() {
    return {data: {value: 'at first, it works'}};
  },

  handleClick: function () {

    // 1. This doesn't work, render is not triggered.
    // Never set state directly because the updated values
    // can still be read, which can lead to unexpected behavior.

    this.state.data.value = 'but React will never know!';

    // 2. This works, because we use setState

    var newData = {value: 'it works 2'};
    this.setState({data: newData});

    // 3. Alternatively you can use React's immutability helpers
    // to update more complex models.
    // Read more: http://facebook.github.io/react/docs/update.html

    var newState = React.addons.update(this.state, {
      data: {value: {$set: 'it works'}}
    });
    this.setState(newState);
 },

  render: function() {
      return <Inner data={this.state.data} handleClick={this.handleClick} />;
  }
});

From React doc

props are immutable: they are passed from the parent and are "owned" by the parent. To implement interactions, we introduce mutable state to the component. this.state is private to the component and can be changed by calling this.setState(). When the state is updated, the component re-renders itself.

From TrySpace: when props (or state) are updated (via setProps/setState or parent) the component re-renders as well.


A reading from Thinking in React:

Let's go through each one and figure out which one is state. Simply ask three questions about each piece of data:

  1. Is it passed in from a parent via props? If so, it probably isn't state.
  2. Does it change over time? If not, it probably isn't state.

  3. Can you compute it based on any other state or props in your component? If so, it's not state.


I'm not sure if I'm answering your question, but I've found that, especially in a large/growing application, the Container/Component pattern works incredibly well.

Essentially you have two React components:

  • a "pure" display component, which deals with styling and DOM interaction;
  • a container component, which deals with accessing/saving external data, managing state, and rendering the display component.

Example

N.B. This example is a probably too simple to illustrate the benefits of this pattern, as it is quite verbose for such a straightforward case.

/**
 * Container Component
 *
 *  - Manages component state
 *  - Does plumbing of data fetching/saving
 */

var PostEditorContainer = React.createClass({
  getInitialState: function() {
    return {
      text: ""
    };
  },

  componentWillMount: function() {
    this.setState({
      text: getPostText()
    });
  },

  updateText: function(text) {
    this.setState({
      text: text
    });
  },

  savePost: function() {
    savePostText(this.state.text);
  },

  render: function() {
    return (
      <PostEditor
        text={this.state.text}
        onChange={this.updateText.bind(this)}
        onSave={this.savePost.bind(this)}
      />
    );
  }
});


/**
 * Pure Display Component
 *
 *  - Calculates styling based on passed properties
 *  - Often just a render method
 *  - Uses methods passed in from container to announce changes
 */

var PostEditor = React.createClass({
  render: function() {
    return (
      <div>
        <input type="text" value={this.props.text} onChange={this.props.onChange} />
        <button type="button" onClick={this.props.onSave} />
      </div>
    );
  }
});

Benefits

By keeping display logic and data/state management separate, you have a re-usable display component which:

  • can easily be iterated with different sets of props using something like react-component-playground
  • can be wrapped with a different container for different behavior (or combine with other components to build larger parts of your application

You also have a container component which deals with all external communication. This should make it easier to be flexible about the way you access your data if you make any serious changes later on*.

This pattern also makes writing and implementing unit tests a lot more straightforward.

Having iterated a large React app a few times, I've found that this pattern keeps things relatively painless, especially when you have larger components with calculated styles or complicated DOM interactions.

*Read up on the flux pattern, and take a look at Marty.js, which largely inspired this answer (and I have been using a lot lately) Redux (and react-redux), which implement this pattern extremely well.

Note for those reading this in 2018 or later:

React has evolved quite a bit since this answer was written, especially with the introduction of Hooks. However, the underlying state management logic from this example remains the same, and more importantly, the benefits that you get from keeping your state and presentation logic separate still apply in the same ways.