State

State

React components will often need dynamic information in order to render. For example, imagine a component that displays the score of a basketball game. The score of the game might change over time, meaning that the score is dynamic. Our component will have to know the score, a piece of dynamic information, in order to render in a useful way.

There are two ways for a component to get dynamic information: props and state. Besides props and state, every value used in a component should always stay exactly the same.

You just spent a long lesson learning about props. Now it’s time to learn about state. props and state are all that you need to set up an ecosystem of interacting React components.

Setting Initial State

A React component can access dynamic information in two ways: props and state.

Unlike props, a component’s state is not passed in from the outside. A component decides its own state.

To make a component have state, give the component a state property. This property should be declared inside a constructor method, like this:

class TodayImFeeling extends React.Component {
  constructor(props) {
    super(props);
    this.state = { mood: ‘decent’ };
  }

  render() {
    return <div>I’m feeling {this.state.mood}!</div>;
  }
}

 

Whoa, a constructor method? super(props)? What’s going on here? Let’s look more closely at this potentially unfamiliar code:

constructor(props) {
  super(props);
  this.state = { mood: ‘decent’ };
}

 

this.state should be equal to an object, like in the example above. This object represents the initial “state” of any component instance. We’ll explain that more soon!

How about the rest of the code? constructor and super are both features of ES6, not unique to React. There is nothing particularly React-y about their usage here. A full explanation of their functionality is outside of the scope of this course, but we’d recommend familiarizing yourself. It is important to note that React components always have to call super in their constructors to be set up properly.

Access a Component’s state

To read a component’s state, use the expression this.state.name-of-property:

render() {
    return <div>I’m feeling {this.state.mood}!</div>;
  }

 

The above code reads a property in its state from inside of its render function.

Just like this.props, you can use this.state from any property defined inside of a component class’s body.

Update state with this.setState

A component can do more than just read its own state. A component can also change its own state.

A component changes its state by calling the function this.setState().

this.setState() takes two arguments: an object that will update the component’s state, and a callback. You basically never need the callback.

Notice that TodayImFeeling component has a state of:

{
  mood:   ‘decent’,

  hungry:  true,

}

 

Now, let’s say that we were to call:

this.setState({ mood: ‘good’ });

 

After that call, the component state would be:

{
  mood:   ‘great’, 

  hungry:   true,


}

 

The hungry part of the state remains unaffected!

this.setState() takes an object, and merges that object with the component’s current state. If there are properties in the current state that aren’t part of that object, then those properties remain how they were.

Call this.setState from Another Function

The most common way to call this.setState() is to call a custom function that wraps a this.setState() call. .makeSomeFog() is an example:

// Example.js

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = { weather: ‘sunny’ };
    this.makeSomeFog = this.makeSomeFog.bind(this);
  }

  makeSomeFog() {
    this.setState({
      weather: ‘foggy’
    });
  }
}

 

Notice how the method makeSomeFog() contains a call to this.setState().

You may have noticed a weird line in there:

this.makeSomeFog = this.makeSomeFog.bind(this);

 

This line is necessary because makeSomeFog()‘s body contains the word this. We’ll talk about it more soon!

Let’s walk through how a function wrapping this.setState() might work in practice. Read this code all the way through.

import React from ‘react’;
import ReactDOM from ‘react-dom’;

class Mood extends React.Component {
  constructor(props) {
    super(props);
    this.state = { mood: ‘good’ };
    this.toggleMood = this.toggleMood.bind(this);
  }

  toggleMood() {
    const newMood = this.state.mood == ‘good’ ? ‘bad’ : ‘good’;
    this.setState({ mood: newMood });
  }

  render() {
    return (
      <div>
        <h1>I’m feeling {this.state.mood}!</h1>
        <button onClick={this.toggleMood}>
          Click Me
        </button>
      </div>
    );
  }
}

ReactDOM.render(<Mood />, document.getElementById(‘app’));

 

Here is how a <Mood />‘s state would be set:

  1. A user triggers an event (in this case a click event, triggered by clicking on a <button></button>).
  2. The event from Step 1 is being listened for (in this case by the onClick attribute on line 20).
  3. When this listened-for event occurs, it calls an event handler function (in this case, this.toggleMood(), called on line 20 and defined on lines 11-14).
  4. Inside of the body of the event handler, this.setState() is called (in this case on line 13).
  5. The component’s state is changed!

Due to the way that event handlers are bound in JavaScript, this.toggleMood() loses its this when it is used on line 20. Therefore, the expressions this.state.mood and this.setState on lines 7 and 8 won’t mean what they’re supposed to… unless you have already bound the correct this to this.toggleMood.

That is why we must bind this.toggleMood to this on line 8.

For an in-depth explanation of this kind of binding trickery, begin with the React docs. For the less curious, just know that in React, whenever you define an event handler that uses this, you need to add this.methodName = this.methodName.bind(this) to your constructor function.

Look at the statement on line 12. What does that do?

Line 12 declares a const named newMood equal to the opposite of this.state.mood. If this.state.mood is “good”, then newMood will be “bad,” and vice versa.

A <Mood /> instance would display “I’m feeling good!” along with a button. Clicking on the button will change the display to “I’m feeling bad!” Clicking again would change back to “I’m feeling good!”, etc. Try to follow the step-by-step walkthrough in Mood.js and see how all of this works.

One final note: you can’t call this.setState() from inside of the render function.

this.setState Automatically Calls render

There’s something odd about all of this. Look at this code:

import React from ‘react’;
import ReactDOM from ‘react-dom’;

const green = ‘#39D1B4’;
const yellow = ‘#FFD712’;

class Toggle extends React.Component {
  constructor(props){
    super(props);
    this.state = { color: green };
    this.changeColor = this.changeColor.bind(this);
  }
 
  changeColor() {
    const newColor = this.state.color == green ? yellow : green;
    this.setState({ color: newColor });
  }
 
  render() {
    return (
      <div style={{background: this.state.color}}>
        <h1>
          Change my color
        </h1>
        <button onClick={this.changeColor}>
  Change color
</button>
      </div>
    );
  }
}

ReactDOM.render(<Toggle />, document.getElementById(‘app’));

 

When a user clicks on the <button></button>, the .changeColor() method is called. Take a look at .changeColor()‘s definition.

.changeColor() calls this.setState(), which updates this.state.color. However, even if this.state.color is updated from green to yellow, that alone shouldn’t be enough to make the screen’s color change!

The screen’s color doesn’t change until Toggle renders.

Inside of the render function, it’s this line:

<div style={{background:this.state.color}}>

 

that changes a virtual DOM object’s color to the new this.state.color, eventually causing a change in the screen.

If you call .changeColor(), shouldn’t you then also have to call .render()again? .changeColor() only makes it so that, the next time that you render, the color will be different. Why can you see the new background right away, if you haven’t re-rendered the component?

Here’s why: Any time that you call this.setState(), this.setState() AUTOMATICALLY calls .render() as soon as the state has changed.

Think of this.setState() as actually being two things: this.setState(), immediately followed by .render().

That is why you can’t call this.setState() from inside of the .render()method! this.setState() automatically calls .render(). If .render() calls this.setState(), then an infinite loop is created.

Build a Stateful and Stateless Component Class

Lets build two React components: a stateful component, and a stateless component. “Stateful” describes any component that has a state property; “stateless” describes any component that does not.

Let’s make a stateful component pass its state to a stateless component.

To make that happen, you need two component classes: a stateful class, and a stateless class.

// Child.js Stateless

import React from ‘react’;

export class Child extends React.Component {
  render() {
    return <h1>Hey, my name is {this.props.name}!</h1>;
  }
}
// Parent.js Stateful
import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { Child } from ‘./Child’;

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { name: ‘Frarthur’ };
  }

  render() {
    return <Child name={this.state.name} />;
  }
}

ReactDOM.render(<Parent />, document.getElementById(‘app’));

 

A <Parent /> is supposed to pass its state to a <Child />.

Before a <Parent /> can pass anything to a <Child />, you need to import Child into Parent.js.

Don’t Update props

Great work! You just passed information from a stateful component to a stateless component. You will be doing a lot of that.

You learned earlier that a component can change its state by calling this.setState(). You may have been wondering: how does a component change its props?

The answer: it doesn’t!

A component should never update this.props. Look at this code to see an example of what not to do.

import React from ‘react’;

class Bad extends React.Component {
  render() {
    this.props.message = ‘yo’; // NOOOOOOOOOOOOOO!!!
    return <h1>{this.props.message}</h1>;
  }
}

 

This is potentially confusing. props and state store dynamic information. Dynamic information can change, by definition. If a component can’t change its props, then what are props for?

A React component should use props to store information that can be changed, but can only be changed by a different component.

A React component should use state to store information that the component itself can change.

If that’s a bit confusing, don’t worry! The next two lessons will be examples.

Child Components Update Their Parents’ state

In the last lesson, you passed information from a stateful, parent component to a stateless, child component.

In this lesson, you’ll be expanding on that pattern. The stateless, child component will update the state of the parent component.

Here’s how that works:

Step 1

The parent component class defines a method that calls this.setState().

For an example, look in the code at the .handleClick() method.

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { ChildClass } from ‘./ChildClass’;

class ParentClass extends React.Component {
  constructor(props) {
    super(props);

    this.state = { totalClicks: 0 };
  }

  handleClick() {
    const total = this.state.totalClicks;

    // calling handleClick will
    // result in a state change:
    this.setState(
      { totalClicks: total + 1 }
    );
  }
}

 

Step 2

The parent component binds the newly-defined method to the current instance of the component in its constructor. This ensures that when we pass the method to the child component, it will still update the parent component.

For an example, look in the code  at the end of the constructor() method.

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { ChildClass } from ‘./ChildClass’;

class ParentClass extends React.Component {
  constructor(props) {
    super(props);

    this.state = { totalClicks: 0 };

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    const total = this.state.totalClicks;

    // calling handleClick will
    // result in a state change:
    this.setState(
      { totalClicks: total + 1 }
    );
  }

  // The stateful component class passes down
  // handleClick to a stateless component class:
  render() {
    return (
      <ChildClass onClick={this.handleClick} />
    );
  }
}

 

Step 3

Once the parent has defined a method that updates its state and bound to it, the parent then passes that method down to a child.

Look in above code  at the prop on line 28.

Step 4

The child receives the passed-down function, and uses it as an event handler.

Look in the code  When a user clicks on the <button></button>, a click event will fire. This will make the passed-down function get called, which will update the parent’s state.

Click through the three files in order, and try to follow their chronology.

 

import React from ‘react’;
import ReactDOM from ‘react-dom’;

export class ChildClass extends React.Component {
  render() {
    return (
      // The stateless component class uses
      // the passed-down handleClick function,
      // accessed here as this.props.onClick,
      // as an event handler:
      <button onClick={this.props.onClick}>
        Click Me!
      </button>
    );
  }
}

 

Define an Event Handler

To make a child component update its parent’s state, the first step is something that you’ve seen before: you must define a state-changing method on the parent.

 

// Parent.js

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { Child } from ‘./Child’;

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = { name: ‘Frarthur’ };
   
    this.changeName = this.changeName.bind(this);
  }
 
  changeName(newName) {
    this.setState({
      name: newName
    });
  }

  render() {
    return <Child name={this.state.name} onChange={this.changeName} />
  }
}

ReactDOM.render(
<Parent />,
document.getElementById(‘app’)
);

 

 

// Child.js

import React from ‘react’;

export class Child extends React.Component {
  constructor(props) {
    super(props);
   
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const name = e.target.value;
    this.props.onChange(name);
  }

  render() {
    return (
      <div>
        <h1>
          Hey my name is {this.props.name}!
        </h1>
        <select id=“great-names” onChange={this.handleChange}>
          <option value=“Frarthur”>
            Frarthur
          </option>

          <option value=“Gromulus”>
            Gromulus
          </option>

          <option value=“Thinkpiece”>
            Thinkpiece
          </option>
        </select>
      </div>
    );
  }
}

 

Pass the Event Handler

Parent must pass this function down to Child, so that Child can use it in an event listener on the dropdown menu.

 

// Child.js

import React from ‘react’;

export class Child extends React.Component {
  constructor(props) {
    super(props);
   
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const name = e.target.value;
    this.props.onChange(name);
  }

  render() {
    return (
      <div>
        <h1>
          Hey my name is {this.props.name}!
        </h1>
        <select id=“great-names” onChange={this.handleChange}>
          <option value=“Frarthur”>
            Frarthur
          </option>

          <option value=“Gromulus”>
            Gromulus
          </option>

          <option value=“Thinkpiece”>
            Thinkpiece
          </option>
        </select>
      </div>
    );
  }
}

 

// Parent.js

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { Child } from ‘./Child’;

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = { name: ‘Frarthur’ };
   
    this.changeName = this.changeName.bind(this);
  }
 
  changeName(newName) {
    this.setState({
      name: newName
    });
  }

  render() {
    return <Child name={this.state.name} onChange={this.changeName} />
  }
}

ReactDOM.render(
<Parent />,
document.getElementById(‘app’)
);

 

Receive the Event Handler

You just passed a function down to Child that can change Parent‘s state!

 

// Child.js

import React from ‘react’;

export class Child extends React.Component {
  constructor(props) {
    super(props);
   
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const name = e.target.value;
    this.props.onChange(name);
  }

  render() {
    return (
      <div>
        <h1>
          Hey my name is {this.props.name}!
        </h1>
        <select id=“great-names” onChange={this.handleChange}>
          <option value=“Frarthur”>
            Frarthur
          </option>

          <option value=“Gromulus”>
            Gromulus
          </option>

          <option value=“Thinkpiece”>
            Thinkpiece
          </option>
        </select>
      </div>
    );
  }
}

 

// Parent.js

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { Child } from ‘./Child’;

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = { name: ‘Frarthur’ };
   
    this.changeName = this.changeName.bind(this);
  }
 
  changeName(newName) {
    this.setState({
      name: newName
    });
  }

  render() {
    return <Child name={this.state.name} onChange={this.changeName} />
  }
}

ReactDOM.render(
<Parent />,
document.getElementById(‘app’)
);

 

Great work! Stateless components updating their parents’ state is a React pattern that you’ll see more and more. Learning to recognize it will help you understand how React apps are organized.

Child Components Update Sibling Components

In lesson 1, you learned your first React programming pattern: a stateful, parent component passes down a prop to a stateless, child component.

In lesson 2, you learned that lesson 1’s pattern is actually part of a larger pattern: a stateful, parent component passes down an event handler to a stateless, child component. The child component then uses that event handler to update its parent’s state.

In this lesson, we will expand the pattern one last time. A child component updates its parent’s state, and the parent passes that state to a sibling component.

One Sibling to Display, Another to Change

One of the very first things that you learned about components is that they should only have one job.

In the last lesson, Child had two jobs:

1 – Child displayed a name.

2 – Child offered a way to change that name.

You should make like Solomon and divide Child in two: one component for displaying the name, and a different component for allowing a user to change the name.

import React from ‘react’;

 

// Child.js
export class Child extends React.Component {
  constructor(props) {
    super(props);

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const name = e.target.value;
    this.props.onChange(name);
  }

  render() {
    return (
      <div>
        <select
          id=“great-names”
          onChange={this.handleChange}>

          <option value=“Frarthur”>Frarthur</option>
          <option value=“Gromulus”>Gromulus</option>
          <option value=“Thinkpiece”>Thinkpiece</option>
        </select>
      </div>
    );
  }
}

 

The new version of Child renders a dropdown menu for changing the name, and that’s it.

Here, the name is displayed! Or at least it will be displayed, once you’ve done a little editing.

That brings us to the essential new concept for this lesson: you will have one stateless component display information, and a different stateless component offer the ability to change that information.

Pass the Right props to the Right Siblings

Look at Parent.js:

// Parent.js
import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { Child } from ‘./Child’;
import { Sibling } from ‘./Sibling’;

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = { name: ‘Frarthur’ };

    this.changeName = this.changeName.bind(this);
  }

  changeName(newName) {
    this.setState({
      name: newName
    });
  }

  render() {
    return (
      <div>
        <Child onChange={this.changeName} />
        <Sibling name={this.state.name} />
      </div>
    );
  }
}

ReactDOM.render(
  <Parent />,
  document.getElementById(‘app’)
);

 

Three things have changed in this file since the last Lesson:

  1. Sibling has been required on line 4.
  2. A <Sibling /> instance has been added to the render function on line 27.
  3. <Sibling /> and <Child /> have been wrapped in a <div></div>, since JSX expressions must have only one outer element.

Display Information in a Sibling Component

You’re on the last step!

You’ve passed the name down to <Sibling /> as a prop. Now <Sibling /> has to display that prop.

 

// Sibling.js

import React from ‘react’;

export class Sibling extends React.Component {
  render() {
const name = this.props.name;
    return (
      <div>
        <h1>Hey, my name is {name}!</h1>
        <h2>Don’t you think {name} is the prettiest name ever?</h2>
        <h2>Sure am glad that my parents picked {name}!</h2>
      </div>
    );
  }
}

 

Handling Forms

Think about how forms work in a typical, non-React environment. A user types some data into a form’s input fields, and the server doesn’t know about it. The server remains clueless until the user hits a “submit” button, which sends all of the form’s data over to the server simultaneously.

In React, as in many other JavaScript environments, this is not the best way of doing things.

The problem is the period of time during which a form thinks that a user has typed one thing, but the server thinks that the user has typed a different thing. What if, during that time, a third part of the website needs to know what a user has typed? It could ask the form or the server and get two different answers. In a complex JavaScript app with many moving, interdependent parts, this kind of conflict can easily lead to problems.

In a React form, you want the server to know about every new character or deletion, as soon as it happens. That way, your screen will always be in sync with the rest of your application.

Input onChange

A traditional form doesn’t update the server until a user hits “submit.” But you want to update the server any time a user enters or deletes any character.

Lets define a function that gets called whenever a user enters or deletes any character. This function will be an event handler. It will listen for change events. You can see an example of an event handler listening for change events in Example.js.

import React from ‘react’;

export class Example extends React.Component {
constructor(props) {
super(props);

this.state = { userInput: };

this.handleChange = this.handleChange.bind(this);
}

handleChange(e) {
  this.setState({
    userInput: e.target.value
  });
}

render() {
  return (
    <input
      onChange={this.handleChange}
      type=“text” />
  );
}
}

 

Set the Input’s Initial State

Good! Any time that someone types or deletes in <input />, the .handleUserInput() method will update this.state.userInput with the <input />‘s text.

Since you’re using this.setState, that means that Input needs an initial state! What should this.state‘s initial value be?

Well, this.state.userInput will be displayed in the <input />. What should the initial text in the <input /> be, when a user first visits the page?

The initial text should be blank! Otherwise it would look like someone had already typed something.

import React from ‘react’;
import ReactDOM from ‘react-dom’;

export class Input extends React.Component {
  constructor(props) {
    super(props);
   
    this.state = { userInput: };
   
    this.handleUserInput = this.handleUserInput.bind(this);
  }
 
  handleUserInput(e) {
    this.setState({userInput: e.target.value});
  }

  render() {
    return (
      <div>
        <input type=“text” onChange={this.handleUserInput} value={this.state.userInput} />
        <h1>{this.state.userInput}</h1>
      </div>
    );
  }
}

ReactDOM.render(
<Input />,
document.getElementById(‘app’)
);

 

Update an Input’s Value

When a user types or deletes in the <input />, then that will trigger a change event, which will call handleUserInput. That’s good!

handleUserInput will set this.state.userInput equal to whatever text is currently in the input field. That’s also good!

There’s only one problem: you can set this.state.userInput to whatever you want, but <input /> won’t care. You need to somehow make the <input />‘s text responsive to this.state.userInput.

Easy enough! You can control an <input />‘s text by setting its value attribute.

Controlled vs Uncontrolled

There are two terms that will probably come up when you talk about React forms: controlled component and uncontrolled component. Like automatic binding, controlled vs uncontrolled components is a topic that you should be familiar with, but don’t need to understand deeply at this point.

An uncontrolled component is a component that maintains its own internal state. A controlled component is a component that does not maintain any internal state. Since a controlled component has no state, it must be controlled by someone else.

Think of a typical <input type=’text’ /> element. It appears onscreen as a text box. If you need to know what text is currently in the box, then you can ask the <input />, possibly with some code like this:

let input = document.querySelector(‘input[type=”text”]’);

let typedText = input.value; // input.value will be equal to whatever text is currently in the text box.

 

The important thing here is that the <input /> keeps track of its own text. You can ask it what its text is at any time, and it will be able to tell you.

The fact that <input /> keeps track of information makes it an uncontrolled component. It maintains its own internal state, by remembering data about itself.

A controlled component, on the other hand, has no memory. If you ask it for information about itself, then it will have to get that information through props. Most React components are controlled.

In React, when you give an <input /> a value attribute, then something strange happens: the <input /> BECOMES controlled. It stops using its internal storage. This is a more ‘React’ way of doing things.

You can find more information about controlled and uncontrolled components in the React Forms documentation.

Review

A React app is basically just a lot of components, setting state and passing props to one another. Now that you have a real understanding of how to use props and state, you have by far the most important tools that you need!