Introduction to State in React
Welcome back to the React Course. In this guide, we are going to go over application's state, and we are going to basically make our app a bit more functional, a bit more operational.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So let's go to our card.js and start here. So what I'd like to do is hit return after this first bracket a little bit. Let's create a constructor. Now in this constructor, we need to do declare some state. We need to say:

card.js

import React, { Component } from 'react';

import Input from './input';

class Card extends Component {

    constructor() {
        super()

        this.state = {}
    }


    render() {
        return (
            <div className="card">
                { Input('Color') }
                { Input('Plural Noun') }
            </div>
        )
    }
}

export default Card;

Now I'm not sure if you've gone over state, but basically what state is: some data that we need to use in our application in our specific component. So again you're going to have a lot of questions, but just hang on and you'll catch on to it eventually. What we need to do is say:

card.js

import React, { Component } from 'react';

import Input from './input';

class Card extends Component {

    constructor() {
        super()

        this.state = {
            color: ''.
            pluralNoun: ''
        }
    }


    render() {
        return (
            <div className="card">
                { Input('Color') }
                { Input('Plural Noun') }
            </div>
        )
    }
}

export default Card;

So now we have access to these two variables in our state. So what we can say and here is:

card.js

import React, { Component } from 'react';

import Input from './input';

class Card extends Component {

    constructor() {
        super()

        this.state = {
            color: ''.
            pluralNoun: ''
        }
    }


    render() {
        return (
            <div className="card">
                <h1>{this.state.color}</h1>
                { Input('Color') }
                { Input('Plural Noun') }
            </div>
        )
    }
}

export default Card;

This will render whatever is in here. So if we type something into color such as Blue, and hit save and go to the browser. It will say blue there. The idea behind this is to get some value in our inputs and mainly have it so when we type in here it changes the value of state.

If you can think about it: if we're typing it into an input and we're changing the value of color that means that this will update because of the way react works. It will render when you type if you set state.

If you google react docs state, you'll see State and Lifecycle. I'm going to hit command + f so I can search. I'm going to say this.setState, and you'll see that down here it says if we use this.setState to get updates on the component to local state. Basically, the idea is, when you call setState it will re-render.

Let's see, it says Using State Correctly. There are three things you should know about setState. Do not modify state directly. So this is a little far-fetched for now. We'll do it in a second but basically, you can't do this. You're supposed to do this to modify state.

large

We're not going to worry about that now, but I guess this is important to talk about. What you'll see it says this will not re-render a component, but by doing this it will re-render a component. So when we change the value of color by using setState it's going to re-render the component. Since we're seeing this.state.color, and this is a new value, you can imagine that this will change.

So what I'd like to do is let's say in the render immediately, we shouldn't set state in here because it will break our app, so if you say:

card.js

import React, { Component } from 'react';

import Input from './input';

class Card extends Component {

    constructor() {
        super()

        this.state = {
            color: ''.
            pluralNoun: ''
        }
    }


    render() {

        this.setState({ color: 'red' })
        return (
            <div className="card">
                <h1>{this.state.color}</h1>
                { Input('Color') }
                { Input('Plural Noun') }
            </div>
        )
    }
}

export default Card;

So what I imagine this will do is it's going to say red, except for then our apps going to crash, because like we just said that state's going to re-render the function. It's going to be re-rendered and then it's going to call it again and then it's going to re-render, and then it's going to call it again and then it can re-render and call it again. So we're going to be stuck in an infinite loop.

Go ahead and google stack overflow error. There's an actual error and in the Java language, not javascript, called Stack Overflow.

So let's head over to our Mad libs app, and you'll see we have an error that says:

large

Basically, if they didn't it might crash our computer or it might crash the browser. That's the most likely possibility, but basically, it's not going to let us do this because it's continually re-rendering it in an infinite way.

So let's get rid of this. Let's hit command + x on this, so we still have it on our clipboard, and so we can paste it. What I'd like to do is create a function in here and let's call it handleInputChange.

card.js

import React, { Component } from 'react';

import Input from './input';

class Card extends Component {

    constructor() {
        super()

        this.state = {
            color: 'BLUE'.
            pluralNoun: ''
        }
    }

    handleInputChange() {
        this.setState({ color: 'red' })
    }

    render() {
        return (
            <div className="card">
                <h1>{this.state.color}</h1>
                { Input('Color') }
                { Input('Plural Noun') }
            </div>
        )
    }
}

export default Card;

What this is going to do is say: we're going to want to call this every time we write some text in here. We're going to want to somehow get the value of input so we can set the state.

So if we can't do it in the render function, because that's going to be an infinite loop, in our constructor if we say handleInputChange at the bottom here. It's not going to immediately. The reason it says is:

large

Basically, you can't setState inside of your constructor. So let's get rid of that, and let's just get it on the input immediately. The first thing I'd like to do is show you a simple way how we can do this without getting involved in our input component too much. So what I'd like to do is in card.js let's just break here and say:

card.js

import React, { Component } from 'react';

import Input from './input';

class Card extends Component {

    constructor() {
        super()

        this.state = {
            color: 'BLUE'.
            pluralNoun: ''
        }
    }

    handleInputChange() {
        this.setState({ color: 'red' })
    }

    render() {

        return (
            <h1>{this.state.color}</h1>
            <input/>
        )

        return (
            <div className="card">
                <h1>{this.state.color}</h1>
                { Input('Color') }
                { Input('Plural Noun') }
            </div>
        )
    }
}

export default Card;

You'll see we have an error. So that's because we're trying to render multiple components here. We technically only want to render one, and you'll see that we have three right here. Technically we have three, but it's also wrapped in a div which makes it a single component. So the error message says: adjacent JSX elements must be wrapped in an enclosing tag.

large

So let's go ahead and cut this create a div:

card.js

import React, { Component } from 'react';

import Input from './input';

class Card extends Component {

    constructor() {
        super()

        this.state = {
            color: 'BLUE'.
            pluralNoun: ''
        }
    }

    handleInputChange() {
        this.setState({ color: 'red' })
    }

    render() {

        return (
            <div className="card">
                <h1>{this.state.color}</h1>
                <input/>
            </div>
        )

        return (
            <div className="card">
                <h1>{this.state.color}</h1>
                { Input('Color') }
                { Input('Plural Noun') }
            </div>
        )
    }
}

export default Card;

Now when you save this, it will work properly. Let's wait for it, and you'll see when we reload the page we have our blue and we have our title here. Okay. So what I'd like to do is make it so whenever we type in here this content updates. So that's what we'll do in the next guide.

Let's open the terminal and say git status, git add ., and let's say git commit -m "setup initial state for card component inputs". I'll see you in the next guide where we will continue learning about state, and how we can map the state from an input to our components state.

Resources