SetState

David Joseph Katz
A free video tutorial from David Joseph Katz
Software Engineer
4.4 instructor rating • 19 courses • 230,755 students

Lecture description

An introduction to the `setState` method: the way to update state in a React component.

Learn more from the full course

React JS Web Development - The Essentials Bootcamp

Bootcamp on the React.js essentials. Gain a strong foundation of the core concepts, and build exciting and useful apps!

10:33:13 of on-demand video • Updated August 2019

  • Learn React the right and learn best practices.
  • Dive into the React engine, and learn how it works under the hood.
  • See how React fits in the big picture of web development.
  • Learn how to build applications from scratch.
  • Cover the crucial concepts of bundling and transpiling, and create frontend application build systems.
English Hi! Previously we added state to the app component in order to control whether or not a bio section should appear. At the moment, displayBio is false by default. So the bio is also going to be hidden by default. But we can add some dynamic functionality to allow the user to flip this boolean in the state. That way the bio section can reappear. So instead of a null value in the false case let's actually have some JSX. So add a pair of parentheses in this false case, let's have a div. In this div, we're gonna have a button element, and this button element, the text of it is gonna say Read more. Cool, now if you have your eye on the app in the browser, and as long as npm run start has been fired in the command line, create-react-app should pick up the change and now, oir read more button is there in the actual application. Nice! Now, when we click on this, some functionality should be triggered to set the displayBio boolean to true. In the state. Let's add that functionality in the class with a new helper method called readMore up in the class. Let's add a new helper method. This method will be called readMore and make sure it's camelCased. So the M is capitalized. Within readMore, Let's change this.state.displayBio to true. So this.state.displayBio is now going to be true. Now it's tempting to write it in this way but this is actually an example of directly modifying the component state object in react. It's a huge bad practice to directly modify the component's state. Instead of doing this react attaches a helper method to the component called setState specifically for updating the values in the state object. The setState method is used by calling this.setState and its input is an object.The keys in this object are whatever keys we want to update in the state. And right now we have one key which is displayBio. Then the value that we want this key to update to: is going to be true so let's make displayBio to true when readMore is fired. Now the key is making this method fire when the button is clicked in react. We can use an onClick property for an element that references a method to fire and under the hood in the react yes engine code react will know to trigger the method when the element is actually clicked. So that goes like this: have an onClick attribute handler. So this is a property on the button element itself and this should point to the read more function. So onClick equals this.readMore within a pair of curly braces. All right go ahead and save the file once you have all this. Then in the browser go ahead and click readMore and the result is perhaps not what you were expecting: instead of the bio now appearing there is an error that says setState can't be used on an undefined object. So this error again is similar to what we had before. This object is undefined and undefined. setState does not work in JavaScript because after all an undefined value doesn't have any methods within it. All right let's dig into this. Rather than calling this.setState in a read more let's do a console.log of the this object within the readMore function. So go ahead and comment out the this.setState line for now we'll now have a console.log of readMore this, and the second parameter is going to be the actual this object that we're looking at. All right, And now in the constructor let's also log the component this. The idea is that we want to see if this object matches the one for the component, for the one that we have here in the readMore function. So by having a console.log of the component this we can make the comparison. So make sure you had both of these lines. All right, If you save the file and then you open up the application logs what you're going to find is that the component this is the app if you expand the app component and then look at the prototype and expand it once more you're going to find that indeed it has access to a setState function. So indeed the component has this.setState. But if you click on the button that this object within the readMore function itself is undefined. Now the reason for this is that class methods don't have logic to create their own this object. A class method written this way is essentially a convenient way to click various methods to fire like a script. It's not an object or a class instance itself. Therefore it doesn't make its own `this` but in this case we still want the setState method attached to this object of the component to be available to this object within the readMore method so one way to do this is to directly attach the method within the constructor to the components of this object. So rather than clearing rather than declaring a class method right away within the constructor we're going to have this stop read more is equal to a function and then if you move the log within here as well as do this.setState, what you're going to find is that now when you try a button click when you do, the readMore this indeed, it matches the app this! Cool! That definitely worked. By attaching the method directly onto this object within the constructor, it has access to the app components of this object. But think of a scenario where we have 5 or even 10 more of these methods for the component. Would we want to write each of these methods within the constructor every time? Probably not. It's a much more cleaner to have this at the class level. So let's remove this the code of read more back within the class method and explore an alternative. So the challenge is that we still want the methods to have access to this object of the component. Luckily in JavaScript we have a special .bind method for methods that allow us to pass this object from one object to another. That way we can bind the this object of the component itself to the helper method and it goes like this. We'll call this.readMore.bind(this). Now this actually produces a new function that is the result of creating a function that has this object from the component bound to this readMore function. So we need to now set this.readMore to that result. All right. If you save this and then uncomment this.setState, you can also leave in the console.log. Head back to the actual application and then click readMore now. And what you're going to find is that the actual bio displays on the application and expands! Woohoo! So we also get the log again that this object within readMore is identical to the app component's. this. Nice. Now that this bio has expanded, let's make sure that we can collapse as well in this expanded version of the state. We're going to add a button that does the opposite of read<ore. It's going to let the user make the application show less. So let's add a new button div after the final paragraph within the true case of this.state.displayBio so this is going to be a button that says show less. Now we can add a helper method that does show this and it essentially does the opposite. It's going to call this.setState and make displayBio now false however rather than having pretty much the same code over again between the two methods. let's make a new method called toggleDisplayBio And what toggleDisplayBio will do is set the state of displayBio to its opposite value whatever it currently may be. So in here we can call this.setState. It's going to change the value of displayBio and make it the opposite of this.state.displayBio using the bang operator. So displayBio is currently false. This will flip it to true if it's true it's going to flip it to false. All right. Now we can get rid of readMore and showLess and we want to make sure that toggleDisplayBio has access to the this object. So toggleDisplayBio is going to be equal to this.toggleDisplay.bind(this); And the showLess button is going to fire that toggleDisplayBio function when it's clicked. And likewise on a click of readMore it will also fire the toggleDisplayBio method. So make sure to have both of those changes as well as the bind of this to toggleDisplayBio Go ahead and save. And in the application now you can click readMore. Likewise you can click show less and it does the opposite. We expand and collapse the bio section! Cool! So that overall wraps up the setState method, and how to properly update the state and the component. Remember it's a rule to never modify the state directly within react. You should call setState to handle situations where you want values in the state to change. You should always supply new objects as values to replace the current values in the state to reinforce this rule. And more importantly to understand why this rule exists in the first place, let's explore what is going on with setState under the hood in the next one!