How to Set State on Multiple Inputs
Welcome back. What I'd like to do in this guide is put a few more inputs on, and then talk about how we can render the rest because we're going to see that it's an inefficient way of doing things.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So let's get started by going to our code here and by putting in the rest of these inputs starting with pluralNoun. Another thing I'd like to do is get rid of this initial 'BLUE' value. So cut that out and let's scroll down here. What we'd like to do is actually somehow get this onChange into our input as well as the value.

large

So what I'd like to do is:

card.js

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

Let's go ahead and see if this is still functional. Let's go back to our application and start typing in here. Of course, we can't see that it's functional, but we can do this. We can console.log it to make sure it's functional.

So what I'll say is:

card.js

    handleInputChange() {
        this.setState({ color: event.target.value })
        console.log(this.state.color)
    }

Save that, and reload the browser. Let's type in here. Let's say hello and you'll see it's not printing over. That is a problem.

large

The reason this isn't working is because we're not doing anything with these values. We need to throw them in the input. So let's go to our input.js file. On the input, we need to pass these in. We need to say:

input.js

const Input = (title, state, onChange) => {
    return (
        <div className="input">
            <input value={state} onChange={onChange}/>
            <label>{title}</label>
        </div>
    )
}

Let's save the application has gone to the browser, and type in the color. You'll see that it's working. I guess we never got rid of that label. So it's up there, we didn't even need to log it. So now that we know it's working, let's just replicate this for the plural noun. You'll notice when we type in here nothing happens.

So we know that it's taking in state and in our card.js we're passing in the state of color. So we just need to pass in this.state.pluralNoun. So let's say:

card.js

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

Now what I'd like to do is pass the same function because all that's going to happen now if we don't pass in the function is it's not going to pass anything in, and it's not going to start. The reason it's not letting us is because we don't have this function. So it's not changing our state and it's empty.

So the value of our input is pluralNoun and it's not changing so it's always going to be empty. Let's go ahead and let's make this work. I'm going to put the function. So one thing I'd like to try is getting rid of this arrow function because it's a more verbose syntax.

Let's just say this.handleInputChange. Let's reload our page and test it on color. It still works.

large

Next thing I'd like to do is pass this into our input on the pluralNoun:

card.js

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

We're going to run into a problem, and that is it's going to do the same exact thing color does, but not for itself. You see. It's setting the state of color right here.

large

The reason we're getting this weird effect with the single letter and it's only putting a single letter in here. This looks extremely strange right. You might be wondering what the heck is going on. It's because we're never changing the value of pluralNoun. So it's only called the next letter we typed in. If we're not changing it, it's always pluralNoun(which is empty), we will never get any value.

Then we're getting the function and it's running when we're typing and it's setting the value of our input, which should be empty, but it's catching the first letter which is then setting it to color. It's only picking up one letter ever because this is always empty. It's only going to pick up the first letter we type, the next letter we type, and then it's going to set it to color. Then it's putting in the next letter we type into color.

Try to understand what I'm talking about. Really make sure you understand how this works before you move on. Pause the video if you have to, and discuss this with someone, or the class, and make sure you understand what's going on.

So what I'd like to do now is talk about why this is happening. It's because we're only setting color, so we need a way to specify which piece of state we want to modify. Now you might think: "Okay, we can just use this, which means we can go to our input and we can take the state and pass it into our onChange." Something like that.

The reason we can't do that is because we don't go in here and say this.state.color. That wouldn't work. You might think: "Okay, we can put brackets around it, and think that that would work." If you go to the page and try it: you'll notice it doesn't work. It's just printing.

So that's not going to work. We need to specify only say color without brackets which means we need to somehow pass this title in your input. Now I don't want to do this by passing this in as a parameter because we have the event as the parameter and the only parameter.

large

So what we can do is remember that we have our event.target.value which means we'll have any other value on our input such as the onChange. If we got here and we print console.log(event.target.onChange). So basically, you've got to think of an event.target as our input because we're getting the value from it and we know that in input.js we have a value, which means we should be able to print this.

You'll see that it's printing undefined. Not sure why, but the point is we can provide a name in here in the input. We can say name={title}. We're passing in our title, but that's not going to work because our title is it's different than this.

large

You'll see that our title is like color with a capital "C" and Plural Noun with a space. So we can't use that here or it's going to not match up what this. It's going to set a new piece of state. You'll see when we type though, it's not printing what we want. The reason it's not printing is because we're saying event.target.onChange. We want to print out the name, so console.log(event.target.name).

Reload the page, and we type in here you'll see it's printing color, and in here it's printing Plural Noun. It's still changing color because we haven't changed the piece of state we're setting. Point is, we have access to this name so all we need to do is pass something different into this name. We need to simply pass in the specific title.

large

So what we can do is on this input we can say:

card.js

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

So now we need to go into our input.js and simply set the name to name and then put the name variable in after our onChange function.

input.js

const Input = (title, state, onChange, name) => {
    return (
        <div className="input">
            <input name={name} value={state} onChange={onChange}/>
            <label>{title}</label>
        </div>
    )
}

Now I'll explain this one more time. We're seeing color and plural noun as a fourth parameter in our input.js. We're taking this fourth parameter and we're throwing it in name, and then in onChange, we're running this function and in here we have access to our input, or event.target, which is the input.

Now with our input, we are saying console.log(event.target.name), which we know the name is right here in input.js. So let's type this out now. Let's type something in here. You'll see it pluralNoun and you're seeing it same color, which is pretty cool.

large

Now we just need to use these on our setState, and we're not just going to say event.target.name because we can't do that. We have to put it in brackets, and now that's going to work. Let's get rid of these console logs, and hit save and let's see if these each have their own unique values.

card.js

    handleInputChange(event) {
        this.setState({ [event.target.name]: event.target.value })      
    }

Now I'm going to get rid of this thing that I typed. I typed this out on here before but it has nothing to do with what we're doing. When I type in here: we can't see it but we're pretty sure it's working because we know color is working. Just to be sure I guess we could say:

card.js

    handleInputChange(event) {
        this.setState({ [event.target.name]: event.target.value })
        console.log(this.state)       
    }

So when we type we see we have color and pluralNoun. When we type color here, we have the color value.

large

That's how we can map over the specific pieces of state with at least one more input. I said we would have been building out more inputs in this guide, but I don't want this to go on too long, and I want this to be specifically a guide on these concepts we just discussed.

So what we're going to do is we're going to commit our code, and then in the next guide we're going to make two more inputs, and then talk about a more efficient way we can do this.

I'll hit command + j to open the terminal in Visual Studio Code, and type in git status, git add ., and let's say git commit -m "modified handleInputChange to handle multiple input cases instead of just the color".

Okay, so I'll see you in the next guide where we will move along with more inputs and then at the end of that guide we'll discuss a more efficient way of rendering these inputs. In the next guide after that, we will implement them.

Resources