Skip to main content

useState

What is state

Components need to “remember” things: the current input value, the current image, the shopping cart. In React, this kind of component-specific memory is called state.

Why we need state

Consider the below component, where the local variable count is incremented when clicking the Increment button.

function App() {
let count = 0;

function handleClick() {
count = count + 1;
}

return (
<>
<div>Value: {count}</div>
<button onClick={handleClick}>Increment</button>
</>
);
}

The handleClick event handler is updating a local variable, count. But two things prevent that change from being visible:

  1. Local variables don’t persist between renders. When React renders this component a second time, it renders it from scratch—it doesn’t consider any changes to the local variables.
  2. Changes to local variables won’t trigger renders. React doesn’t realize it needs to render the component again with the new data.

To update a component with new data, two things need to happen:

  1. Retain the data between renders.
  2. Trigger React to render the component with new data (re-rendering).

The useState Hook provides those two things:

  1. A state variable (count) to retain the data between renders.
  2. A state setter function (setCount) to update the variable and trigger React to render the component again.
function App() {
let [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<>
<div>Value: {count}</div>
<button onClick={handleClick}>Increment</button>
</>
);
}

useState Input parameter

  • initialState: The value you want the state to be initially. If you pass a function as initialState, it will be treated as an initializer function. It should be pure, should take no arguments, and should return a value of any type. React will call your initializer function when initializing the component, and store its return value as the initial state.

Avoiding recreating the initial state

  • In the below example, Although the result of createInitialTodos() is only used for the initial render, you’re still calling this function on every render. This can be wasteful if it’s creating large arrays or performing expensive calculations.
function TodoList() {
const [todos, setTodos] = useState(createInitialTodos());
// ...
  • To solve this, you may pass it as an initializer function to useState instead:
function TodoList() {
const [todos, setTodos] = useState(createInitialTodos);
// ...

Where to use hooks

  • Hooks functions starting with use can only be called at the top level of your components or your own Hooks. You can’t call Hooks inside conditions, loops, or other nested functions.

  • You “use” React features at the top of your component similar to how you “import” modules at the top of your file.

useState Features

  • The useState Hook returns a pair of values: the current state and the function to update it.
  • You can have more than one state variable. Internally, React matches them up by their order.
  • State is private to the component. If you render it in two places, each copy gets its own state. Each Gallery component in the below example will have it's own private state.
export default function Page() {
return (
<div className="Page">
<Gallery />
<Gallery />
</div>
);
}