# useState

![](https://3779609961-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF_PCkC6EJQO74OPq_g%2Fuploads%2FOniwpr7I86Jqd7GYENNH%2FuseState?alt=media\&token=8ccfe95d-6996-4a7c-a197-6a6be0501f40)

The signature for the `useState` Hook is as follows:

![](https://3779609961-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF_PCkC6EJQO74OPq_g%2Fuploads%2FGt4Luc06pt6otFGcYdsa%2FuseState2.png?alt=media\&token=9b9664dc-d0c4-4bcb-a55f-3781f7917305)

Here, `state` and `setState` refer to the state value and updater function returned on invoking `useState` with some `initialState`.

It’s important to note that when your component first renders and invokes `useState`, the `initialState` is the returned state from `useState`.

## Declare State Variable <a href="#declare-state-variable" id="declare-state-variable"></a>

{% hint style="warning" %}
**Always remember that the value of the state is always the initial state value on the first render**
{% endhint %}

```jsx
 const [state] = useState(100)
 return <div> State variable is {state}</div>
```

## Update State Variable <a href="#update-state-variable" id="update-state-variable"></a>

Also, to update state, the state updater function `setState` should be invoked with a new state value, as shown below:

![](https://3779609961-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF_PCkC6EJQO74OPq_g%2Fuploads%2FqHtoDdXPn2ir2C9XY3TR%2Fcode.png?alt=media\&token=f3f170ce-1813-4d41-bb38-26043833e7f9)

By doing this, a new re-render of the component is queued. `useState` guarantees that the `state` value will always be the most recent after applying updates.

![](https://3779609961-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF_PCkC6EJQO74OPq_g%2Fuploads%2F7U8oiaZs6zMbnMfNaKpG%2Fre-render%20queue.gif?alt=media\&token=22af1b76-81b7-4116-8095-d690b692a5b7)

For referential checks, the `setState` function’s reference never changes during re-renders.

{% hint style="info" %}
**If you try to update state with the same value as the current state, React won’t render the component children or fire effects, e.g., `useEffect` callbacks. React compares previous and current state via the** [**`Object.is` comparison algorithm**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description)**; if they are equal, it ignores the re-render.**

**It’s important to note that in some cases, React may still render the specific component whose state was updated. That’s OK because React will&#x20;*****not*****&#x20;go deeper into the tree, i.e., render the component’s children.**
{% endhint %}

Here an example of a Counter component that use `useState` to update the counter by one for each click

```jsx
const Counter = () => {
  const [counter, setCounter] = useState(0)
  const handleClick = () => setCounter(counter + 1)

  return (
    <div>
      Counter:{counter}
      <div>
        <button onClick={handleClick}>add to the counter </button>
      </div>
    </div>
  )
}
```

### Functional updates <a href="#functionalupdates" id="functionalupdates"></a>

The state setter function returned by `useState` can be invoked in two ways. The first is by passing a new value directly as an argument:

```jsx
const [state, setState] = useState(initialStateValue)

// update state as follows
setState(newStateValue)
```

This is correct and works perfectly in most cases. However, there are cases where a different form of state update is preferred: ***functional updates***.

Here’s the example above revised to use the functional update form:

```jsx
const [state, setState] = useState(initialStateValue)

// update state as follows
setState((previousStateValue) => newValue)
```

{% hint style="info" %}
You pass a function argument to `setState`. Internally, React will invoke this function with the previous state as an argument. Whatever is returned from this function is set as the new state.
{% endhint %}

When your new state depends on the previous state value — e.g., a computation — favor the functional state update. Since `setState` is async, React guarantees that the previous state value is accurate.

Here’s an example:

```jsx
const Counter = () => {
  const [count, setCount] = useState(0);
  return (
    <>
      <p>Count value is: {count}</p>
      <button onClick={() => setCount(0)}>Reset</button>
      <button 
        onClick={() => setCount(prevCount => prevCount + 1)}>
        Plus (+)
      </button>
      <button 
        onClick={() => setCount(prevCount => prevCount - 1)}>
       Minus (-)
      </button>
    </>
  );
}
```

In the example above, the button grows every time it’s clicked. Since the new state value depends on the old, the functional update form of `setState` is preferred.

### Lazily initializing state <a href="#lazilyinitializingstate" id="lazilyinitializingstate"></a>

The `initialState` argument to `useState` is only used during your initial render.

![](https://3779609961-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF_PCkC6EJQO74OPq_g%2Fuploads%2FbPNfty19WGfCahU9o3FL%2Fre-render%20queue%20\(1\).gif?alt=media\&token=bce0e4e3-5be9-4fe4-a993-71a3a5f5fa0e)

```jsx
// subsequent prop updates are ignored 
const App = ({myProp}) => {
  const [state, setState] = useState(myProp)
}
// only the initial myProp value on initial render is passed as initialState. subsequent updates are ignored.
```

### Initialize state from function

If the initial state is a result of an expensive computation, you could also pass a function, which will be invoked only on initial render:

```
const [state, setState] = useState(() => yourExpensiveComputation(props))
```

As opposed to just passing an initial state value, state could also be initialized from a function, as shown below:

```jsx
const Component = () => {
  
  const [token] = useState(() => {
  // this will only render in first initial render
    const token = window.localStorage.getItem("sensetive-data");
    return token || "please don't put sensetive data in local storage 😢😢😢😢"
  })

  return <div>Token is {token}</div>
}
```

### **Use with objects**

As opposed to strings and numbers, you could also use an object as the initial value passed to `useState`.

Note that you have to pass the entire object to the `useState` updater function because the object is replaced, not merged.This is very different from how `this.setState` worked in classes!

```jsx
function Component() {
  const [state, setState] = useState({ name: "Mayssa" });
  const updateState = () => setState({ occupation: "Teacher" });
  return (
    <>
      <pre>{JSON.stringify(state)}</pre>
      <button onClick={updateState}>update state</button>
    </>
  );
}
```

So in order to add an property to the object, we’re using the ES6 spread operator `...` to copy the existing properties into the new object,&#x20;

```jsx
const updateState = () => { setState((prevState) => ({ ...prevState, occupation: "Teacher" })); };
```

Pass a function to `setState` and return a merged object by using the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) ([`Object.assign` also works](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)).

### **Use with arrays**

Remember: state can hold any kind of value! Here’s an example of useState holding an array.

Typing into the box and hitting Enter will add an item to the list.

```jsx
function ListOfThings() {
  const [itemsList, setItemsList] = useState([]);
  const [itemName, setItemName] = useState("");

  const addItem = event => {
    event.preventDefault();
    setItemsList([
      ...itemsList,
      {
        id: itemsList.length, // just for the sake of the example , never put the index of the item in the array as an id
        name: itemName
      }
    ]);
    setItemName("");
  };

  return (
    <>
      <form onSubmit={addItem}>
        <label>
          <input
            name="item"
            type="text"
            value={itemName}
            onChange={e => setItemName(e.target.value)}
          />
        </label>
      </form>
      <ul>
        {itemsList.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </>
  );
}
```

Notice we’re calling useState with an initial value of an empty array `[]`,&#x20;

Such as objects, in order to add an item to the array, we’re using the ES6 spread operator `...` to copy the existing items into the new array, and inserting the new item at the end.

### **M**ultiple calls to useState

If you want to store multiple values in a function component, you’ve got a couple options:

* call `useState` more than once
* shove everything into an object

There’s nothing wrong with calling `useState` multiple times, and in most cases, that’s how I store multiple values. Once you get over 4 or 5 useState calls it gets a bit unwieldy, but if you’re fine with it, React is too.

Multiple state variables may be used and updated from within a functional component as shown below:

```jsx
const Component =() => {
  const [age, setAge] = useState(19)
  const [siblingsNum, setSiblingsNum] = 
    useState(10)

  const handleAge = () => setAge(age + 1)
  const handleSiblingsNum = () => 
      setSiblingsNum(siblingsNum + 1)
 

  return (
    <div>
      <p>Today I am {age} Years of Age</p>
      <p>I have {siblingsNum Multiple state variables may be used and updated from within a functional component as shown below:} siblings</p>

      <div>
        <button onClick={handleAge}>
          Get older! 
        </button>
        <button onClick={handleSiblingsNum}>
            More siblings! 
        </button>
      </div>
    </div>
  )
}
```

If expensive calculations are done within the body of your functional component, i.e., before the return statement, consider optimizing these with `useMemo`.(we will cover [useMemo  in another section](https://maissen.gitbook.io/react-grimoire/react-hooks/usememo))&#x20;

## References and articles :&#x20;

{% embed url="<https://juejin.cn/post/6844903833764642830>" %}
