Understanding and Handling Local State in React
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Next.js Complex State Management Patterns with RSC course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Next.js Complex State Management Patterns with RSC, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
[00:00 - 00:21] Hello and welcome to a new lesson. In this video we're going to be focusing on local state and how to handle it. Some of these concepts that we're going to be seeing, we've already kind of covered them or hinted at in previous lessons, so they might already be familiar to you, especially also if you come from previous versions of Next or even from React itself.
[00:22 - 00:34] So, just if even if you already know them, just it's a good reminder of how they work. So let's get going. So the first thing to focus on is that local state is data that we track at a components level.
[00:35 - 00:46] It might be something like a toggle or a more complex data like form values. It is defined, used and updated all within the same component and that is what makes it local.
[00:47 - 01:08] So we talked about this in previous videos and as I mentioned, the key for this state or this data to be considered local state is that it can be handled entirely by the component that creates it, no one else or no other component needs it. So to initialize local state, React gives us the useState hook that we've seen already.
[01:09 - 01:17] When you call the useState function or hook, you get a pair, essentially. You get the current value of the state and a function to update it.
[01:18 - 01:28] I kinda already hint at this on previous videos, but let's fully understand what we're seeing here on screen. This is our state variable count, it is initialized to 0. This is our starting point.
[01:29 - 01:33] Now, consider the following. What you're seeing here is called array destructuring.
[01:34 - 01:42] If you're not familiar with the term, the useState hook is, in fact, whenever you call it, it's returning an array of values, essentially. There's nothing more to it.
[01:43 - 01:56] And what we're doing here is thanks to JavaScript destructuring syntax, we're reassigning those values into local and independent variables. The first of those values is the current state value, as I mentioned, and we put it in the constant count.
[01:57 - 02:09] And then the other one, the second is always going to be the setter function, the function that we're going to be using to update that value. Because as we've seen already, you can't really update the variable directly.
[02:10 - 02:17] You can't really update the count here directly. You can't just say count equals one, even if it was declared with let instead of const.
[02:18 - 02:41] And that happens because remember that React needs to re-render your component, and it knows to do so whenever you use the setter function. So a good practice to avoid writing code that might get you in trouble is to simply define these two values, these two variables, as constants instead of using the let or even the var keyword.
[02:42 - 03:05] That means that even if you end up accidentally writing code that tries to directly assign a value to the count variable, the interpreter will let you know immediately that you're trying to do an invalid action, because you can't really assign a value to a const once it's been initialized. So that's a very small but interesting good practice that you want to consider adopting if you haven't yet on your projects.
[03:06 - 03:13] So as I mentioned before, updating the local state is very straightforward. We will use the setter function that we get from the useState hook.
[03:14 - 03:31] Again, this is needed because React needs to know that you want to update the state and that the component needs to be re-rendered accordingly. So here we have a very simple counter-component that uses this function to update the count that we defined before.
[03:32 - 03:43] Every time we click a button, the button increments the count, each time it's clicked, and the displayed count updates accordingly. That happens because the actual full component gets re-rendered.
[03:44 - 04:17] So the last thing I want to mention about this hook is that while you will see every React example out there or project using it, you will see that the setter function for your state variable is always called set, and then it uses a capitalized version of the name of your state variable. This is just a naming convention, a handy naming convention that everyone uses to make sure that we know that the set that we're using the setter function.
[04:18 - 04:35] But in reality, given that React is giving you that direct reference to the setter function as the second value of the array that is being returned, you could potentially name it however you want it. Honestly, this is just a handy naming convention. Keep using it because it will make your life easier.
[04:36 - 04:45] But just keep in mind that this is something that you can change or adapt however you want. You're not forced to following it to make it work.
[04:46 - 05:02] An interesting thing to know is that the value that you passed to the useState hook is going to be the initial value for your state variable. You can pass a direct JavaScript value there like a string, even an object or an array, whatever you want to.
[05:03 - 05:12] But you can also just use props. For example, it's a very common practice to use props from your component as default values for these state variables.
[05:13 - 05:27] And you can even do something more complex which is define a function like I'm showing here in the example, a function that will be called whenever the state variable is defined. And this function will return the initial value.
[05:28 - 05:37] You could do something as complex as getting it from somewhere else down the DOM or performing some synchronous calculation. Just keep in mind that has to be synchronous.
[05:38 - 06:07] And whatever you do here, the key thing to remember is that this function is going to be called just once. The first time this component is rendered and the first time the state variable is defined, that's when this setter function, if you will, will be called on every subsequent state update and re-render of your component this step is going to be ignored because React will already know the current value of your state variable and it will not replace it with this function.
[06:08 - 06:24] So in this example, we see a full component that is using an initial value for the default state of our toggle. The toggle being our local state variable and again, this is a very common practice that you can definitely implement in your components.
[06:25 - 06:39] As we interact with the button, the state is going to change, the component is going to re-render and you'll see the toggle value being on and off. But obviously the initial value provider is not going to be remembered anymore.
[06:40 - 06:51] However, the first time it renders, it's a good thing to be able to control that state through props. So as a summary, local state is the foundation of interactivity to components.
[06:52 - 07:06] Remember that whenever you update the local state, your components are going to be re-rendered. With the useState hook, you have a powerful and intuitive way to manage dynamic information. You can define default values, you can use complex logic to define those default values, however you want.
[07:07 - 07:26] So remember to properly initialize your state variables. Remember that to update them responsibly in the sense that you have to know when they should be updated. The effect that the update is going to have on your component, we've seen it already. And also very importantly, remember that the update is an asynchronous process.
[07:27 - 07:39] If you do that, then your components will always be responsive to user interactions and they will not cause any performance degradation to the entire application. So in the next video, we're going to be looking at global state more in depth.
[07:40 - 07:42] But in the meantime, keep coding and I'll see you then.