DEV Community

Cover image for From JS to React: Why do I need useState()?
Andres Castro
Andres Castro

Posted on • Updated on

From JS to React: Why do I need useState()?

When I started learning React I was completely blown away by the idea of Components and JSX. Not only was React my first JS framework, but I was also practicing a lot of DOM manipulation in Vanilla JS. I'm sure you understand what I mean if you have gone through this. For those who do not: Dom manipulation is a painful, verbose, and traumatizing experience. Well, at least if you desire to build a fully interactive page with great UX.

I actually overlooked the idea of State when I began, it just didn't seem as important. Of course, that happens if you don't quite understand why you need such a new concept. And so, my React Journey began. Pretty soon, I ran into trouble and my logic was making no sense. After quite a few hours of reading and a good dose of trial and error, I really understood my mistake and got a good grasp of what State is and, most importantly, why it is needed.

To understand state easily, let's first understand why using React components is different from JS DOM Manipulation or, for that matter, regular JS code, even without messing around with the DOM.

Regular JS:

In JavaScript, we can define variables and mutate/reassign these variables throughout our scripting. Regarding the differences with React, there are 3 key points:
1) We can change any variable's value at anytime(as long as it is defined with 'let' and you use the correct scope).
2) DOM manipulation simply adds, eliminates, or modifies the HTML that is being displayed.
3) Whenever we reload the page, all of our variables go back to the original value they had when defined.

React:

When using React, you render components with JSX (which seems like a combination of HTML and JS). Whenever you make a change to those components, React makes a new rendering. Whether it is an update to the component, swapping components or even just eliminating them. In any case, you are rendering again. Let's compare our 3 key points from JS:
1) We can still define variables and change them.
2) Now, we are not directly manipulating the DOM but rather rerendering our components.
3) Our variables will reset when we reload or when we re-render.

So, what does that mean? Quite simple: you cannot make changes to what is seen on the screen without losing your current variable values. That is a problem.... but it has a solution: useState

What is State?

In simple words, State, in the context of React, is the memory of a component. Thanks to it, our variable's values can perdure throughout the lifecycle of our apps' components (mount -> update -> unmount). So, whenever we want a variable to keep its current value even if the component is rerendered, we need to convert that variable into a state variable.

What is useState()?

useState() is what we call a "Hook". But let's not get into hooks right now. In practice, useState() is what we use to define state variables. Most of our variables in React will be defined this way.

How to useState()?

Using state seems a little bit awkward at the beginning, but it's actually pretty simple. Before showing you, be aware I'm assuming you do understand the basics of React Functional Components. Let's look at this code, which I separated into 3 main sections:


import React, { useState } from 'react';

function StateExample() {

 //State Variable:
  const [randomNumber, setRandomNumber] = useState(0);

  //Modifying Function:
  const generateNumber = () => {
    let newNumber = Math.floor(Math.random() * 1000); //Regular Variable
    setRandomNumber(newNumber);
  };

  //JSX to be Rendered:
  return (
    <div>
      <button onClick={generateNumber}> Generate Number</button>
      <div> {randomNumber} </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The component above generates a RandomNumber whenever you click the button and displays it in the div. Let's go through it.

- State Variable: This is how we define our state variables. It's an array with 2 elements. The first element defines the variable itself. The second element defines a function for modifying the variable, which we can call setFunction (I'll expand on this soon). Lastly, we call useState(), which was previously imported. Whatever you place inside this method will be the initial value when the component is mounted (initial value = 0 in this example).

- Modifying Function: There are several things going on here. First of all, let's talk about setRandomNumber. What you need to keep in mind is this: state variables cant be reassigned as regular variables. The second argument in the useState assignment is a function made especially for this and it will basically reassign the variable to whatever argument you pass through it. It is common to name it 'set + Variablename' just for readability. In this particular example, we are reassigning randomNumber with the value newNumber. The next thing we want to look into is: why have our setFuncion inside another function? Basically, whenever you call a function into your JSX, it will automatically run indefinitely. To avoid this, we attach our function to a variable (generateNumber) through arrow function notation. This way, we will only modify the state when we call upon it.

- JSX: Nothing fancy, just our button attached to an onClick event listener that triggers our state update (generateNumber) and thus updates the value on the div.

Note on setFunction: Sometimes, you want your new state variable to depend on its last value. In these situations, the usage is a little bit more complicated. For example, let's say we don't want to display a random number, but rather add a new random number to our last number and display the result. That would look like this:

  const generateNumber = () => {
    let newNumber = Math.Floor(Math.Random()*1000)  //Regular Variable
    setRandoNumber( randomNumber => randumNumber + newNumber )
}
Enter fullscreen mode Exit fullscreen mode

So basically, what you do is pass an arrow function as the argument of the setFunction. This arrow function will receive the state variable as its argument and return whatever value we need for reassignment (in this case, the addition).

Wrapping Up.

Reacts nature is not compatible with the assignment logic we have in vanilla JS. Instead, we need to use state variables that can make our values perdure. This is, in my opinion, the starting point for "thinking in React". Now that you understand the basic idea of state, I would highly suggest moving forward to understanding how this works in conjunction with props within the components Hierarchy of any app and learning how to decide where to define state and where to pass it as a prop. Also, there is a lot going on behind the curtain when managing state. It certainly is a good idea to learn about state asynchronicity and how to deal with it. Let me know if you would like posts on these topics.

Top comments (0)