Home » Reactjs » What is the difference between state and props in React?

What is the difference between state and props in React?

Posted by: admin November 29, 2017 Leave a comment

Questions:

I was watching a Pluralsight course on React and the instructor stated that props should not be changed. I’m now reading an article (uberVU/react-guide) on props vs. state and it says

Both props and state changes trigger a render update.

Later in the article it says:

Props (short for properties) are a Component’s configuration, its options if you may. They are received from above and immutable.

  • So props can change but they should be immutable?
  • When should you use props and when should you use state?
  • If you have data that a React component needs, should it be passed through props or setup in the React component via getInitialState?
Answers:

Props and state are related. The state of one component will often become the props of a child component. Props are passed to the child within the render method of the parent as the second argument to React.createElement() or, if you’re using JSX, the more familiar tag attributes.

<MyChild name={this.state.childsName} />

The parent’s state value of childsName becomes the child’s this.props.name. From the child’s perspective, the name prop is immutable. If it needs to be changed, the parent should just change its internal state:

this.setState({ childsName: 'New name' });

and React will propagate it to the child for you. A natural follow-on question is: what if the child needs to change its name prop? This is usually done through child events and parent callbacks. The child might expose an event called, for example, onNameChanged. The parent would then subscribe to the event by passing a callback handler.

<MyChild name={this.state.childsName} onNameChanged={this.handleName} />

The child would pass its requested new name as an argument to the event callback by calling, e.g., this.props.onNameChanged('New name'), and the parent would use the name in the event handler to update its state.

handleName: function(newName) {
   this.setState({ childsName: newName });
}

Questions:
Answers:

For parent-child communication, simply pass props.

Use state to store the data your current page needs in your controller-view.

Use props to pass data & event handlers down to your child components.

These lists should help guide you when working with data in your components.

Props

  • immutable (let’s react do fast reference checks)
  • used to pass data down from your view-controller(your top level component)
  • better performance, use this to pass data to child components

State

  • Should be managed in your view-controller(your top level component)
  • mutable
  • worse performance
  • don’t access this to from child components, pass it down with props instead

For communication between two components that don’t have a
parent-child relationship, you can set up your own global event
system. Subscribe to events in componentDidMount(), unsubscribe in
componentWillUnmount(), and call setState() when you receive an event.
Flux pattern is one of the possible ways to arrange this.
https://facebook.github.io/react/tips/communicate-between-components.html

What Components Should Have State?

Most of your components should simply take some data from props and
render it. However, sometimes you need to respond to user input, a
server request or the passage of time. For this you use state.

Try to keep as many of your components as possible stateless. By doing
this you’ll isolate the state to its most logical place and minimize
redundancy, making it easier to reason about your application.

A common pattern is to create several stateless components that just
render data, and have a stateful component above them in the hierarchy
that passes its state to its children via props. The stateful
component encapsulates all of the interaction logic, while the
stateless components take care of rendering data in a declarative way.
https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#what-components-should-have-state

What Should Go in State?

State should contain data that a component’s event handlers may change
to trigger a UI update. In real apps this data tends to be very small
and JSON-serializable. When building a stateful component, think about
the minimal possible representation of its state, and only store those
properties in this.state. Inside of render() simply compute any other
information you need based on this state. You’ll find that thinking
about and writing applications in this way tends to lead to the most
correct application, since adding redundant or computed values to
state means that you need to explicitly keep them in sync rather than
rely on React computing them for you.
https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#what-should-go-in-state

Questions:
Answers:

The props vs state summary I like best is here: https://github.com/uberVU/react-guide/blob/master/props-vs-state.md Big hat tip to those guys. Below is an edited version of that page:


props vs state

tl;dr If a Component needs to alter one of its attributes at some point in time, that attribute should be part of its state, otherwise it should just be a prop for that Component.


props

Props (short for properties) are a Component’s configuration. They are received from above and immutable as far as the Component receiving them is concerned. A Component cannot change its props, but it is responsible for putting together the props of its child Components. Props do not have to just be data — callback functions may be passed in as props.

state

The state is a data structure that starts with a default value when a Component mounts. It may be mutated across time, mostly as a result of user events.

A Component manages its own state internally. Besides setting an initial state, it has no business fiddling with the state of its children. You might conceptualize state as private to that component.

Changing props and state

                                                   props   state
    Can get initial value from parent Component?    Yes     Yes
    Can be changed by parent Component?             Yes     No
    Can set default values inside Component?*       Yes     Yes
    Can change inside Component?                    No      Yes
    Can set initial value for child Components?     Yes     Yes
    Can change in child Components?                 Yes     No
  • Note that both props and state initial values received from parents override default values defined inside a Component.

Should this Component have state?

State is optional. Since state increases complexity and reduces predictability, a Component without state is preferable. Even though you clearly can’t do without state in an interactive app, you should avoid having too many Stateful Components.

Component types

Stateless Component Only props, no state. There’s not much going on besides the render() function. Their logic revolves around the props they receive. This makes them very easy to follow, and to test.

Stateful Component Both props and state. These are used when your component must retain some state. This is a good place for client-server communication (XHR, web sockets, etc.), processing data and responding to user events. These sort of logistics should be encapsulated in a moderate number of Stateful Components, while all visualization and formatting logic should move downstream into many Stateless Components.

sources

Questions:
Answers:

Basically, props and state are two ways the component can know what and how to render. Which part of the application state belongs to state and which to some top-level store, is more related to your app design, than to how React works. The simplest way to decide, IMO, is to think, whether this particular piece of data is useful for application as a whole, or it’s some local information. Also, it’s important to not duplicate state, so if some piece of data can be calculated from props – it should calculated from props.

For example, let’s say you have some dropdown control (which wraps standart HTML select for custom styling), which can a) select some value from list, and b) be opened or closed (i.e., the options list displayed or hidden).
Now, let’s say your app displays a list of items of some sort and your dropdown controls filter for list entries. Then, it would be best to pass active filter value as a prop, and keep opened/closed state local. Also, to make it functional, you would pass an onChange handler from parent component, which would be called inside dropdown element and send updated information (new selected filter) to the store immediately. On the other hand, opened/closed state can be kept inside dropdown component, because the rest of the application doesn’t really care if the control is opened, until user actually changes it value.

The following code is not completely working, it needs css and handling dropdown click/blur/change events, but I wanted to keep example minimal. Hope it helps to understand the difference.

const _store = {
    items: [
    { id: 1, label: 'One' },
    { id: 2, label: 'Two' },
    { id: 3, label: 'Three', new: true },
    { id: 4, label: 'Four', new: true },
    { id: 5, label: 'Five', important: true },
    { id: 6, label: 'Six' },
    { id: 7, label: 'Seven', important: true },
    ],
  activeFilter: 'important',
  possibleFilters: [
    { key: 'all', label: 'All' },
    { key: 'new', label: 'New' },
    { key: 'important', label: 'Important' }
  ]
}

function getFilteredItems(items, filter) {
    switch (filter) {
    case 'all':
        return items;

    case 'new':
        return items.filter(function(item) { return Boolean(item.new); });

    case 'important':
        return items.filter(function(item) { return Boolean(item.important); });

    default:
        return items;
  }
}

const App = React.createClass({
  render: function() {
    return (
            <div>
            My list:

            <ItemList   items={this.props.listItems} />
          <div>
            <Dropdown 
              onFilterChange={function(e) {
                _store.activeFilter = e.currentTarget.value;
                console.log(_store); // in real life, some action would be dispatched here
              }}
              filterOptions={this.props.filterOptions}
              value={this.props.activeFilter}
              />
          </div>
        </div>
      );
  }
});

const ItemList = React.createClass({
  render: function() {
    return (
      <div>
        {this.props.items.map(function(item) {
          return <div key={item.id}>{item.id}: {item.label}</div>;
        })}
      </div>
    );
  }
});

const Dropdown = React.createClass({
    getInitialState: function() {
    return {
        isOpen: false
    };
  },

  render: function() {
    return (
        <div>
            <select 
            className="hidden-select" 
          onChange={this.props.onFilterChange}
          value={this.props.value}>
            {this.props.filterOptions.map(function(option) {
            return <option value={option.key} key={option.key}>{option.label}</option>
          })}
        </select>

        <div className={'custom-select' + (this.state.isOpen ? ' open' : '')} onClick={this.onClick}>
            <div className="selected-value">{this.props.activeFilter}</div>
          {this.props.filterOptions.map(function(option) {
            return <div data-value={option.key} key={option.key}>{option.label}</div>
          })}
        </div>
      </div>
    );
  },

  onClick: function(e) {
    this.setState({
        isOpen: !this.state.isOpen
    });
  }
});

ReactDOM.render(
  <App 
    listItems={getFilteredItems(_store.items, _store.activeFilter)} 
    filterOptions={_store.possibleFilters}
    activeFilter={_store.activeFilter}
    />,
  document.getElementById('root')
);

Questions:
Answers:

State is the way react deals with the information held by your component.

Let’s suppose you have a component which need to fetch some data from the server. You usually would want to inform the user if the request is processing, if it has failed, etc. This is a piece of information which is just relevant for that specific component. This is where state enters the game.

Usually the best way to define state is as follows:

class MyComponent extends React.Component {
  constructor() {
    super();
    this.state = { key1: value1, key2: value2 }    
  }
}

but in the latests implementations of react native you can just do:

class MyComponent extends React.Component {
  state = { key1: value1, key2: value2 }    
}

These two examples execute in the exact same way, it’s just a syntax improvement.

So, what is different from just using object attributes as we always have in OO programming? Usually, the information held in your state is not meant to be static, it will change over time and your View will need to update in order to reflect this changes. State offers this functionality in a simple way.

State IS MEANT TO BE INMUTABLE! and I cannot make enough stress on this. What does this means? It means that you should NEVER do something like this.

 state.key2 = newValue;

The proper way of doing it is:

this.setState({ key2: newValue });

Using this.setState your component runs through the update cycle and if any part of the state changes, your Component render method will be called again to reflect this changes.

Check the react docs for an even more expanded explanation:
https://facebook.github.io/react/docs/state-and-lifecycle.html

Questions:
Answers:

In answer to the initial question about props being immutable, they are said to be immutable as far as the child component is concerned but are changeable in the parent.