What is the case where you use useState
's initial value as a function?
Is there any difference from just passing a value?
e.g.
const [state, setState] = useState(() => someValue)
What is the case where you use useState
's initial value as a function?
Is there any difference from just passing a value?
e.g.
const [state, setState] = useState(() => someValue)
You use it when you want the computation of that initial state to happen only once.
Because if you use an expression instead say:
const [state, setState] = useState(compute());
React saves the initial result of compute()
once and ignores it on the next renders. But the compute
function is still called on each render. This can be wasteful.
If you pass a function instead, the function is invoked only once.
From the docs:
const [state, setState] = useState(initialState);
The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render
const [state, setState] = useState(() => { const initialState = someExpensiveComputation(props); return initialState; });
Also, in case you pass function as the argument to useState
like the question is asking, it must satisfy certain requirements:
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.
If you want to use useState's initial value as a function, you need to use currying :
const [state, setState] = useState(() => () => someValue);
This is because in the documentation, useState executes the provided function and considers its result as the initial value.
Using currying, () => someValue
is returned and considered to be the intial value.
The reason why wrapping in a function is less computationally heavy is because react will rerun the component function when props change. If useState() has a computation inside like useState(heavyComputation())
, JavaScript will run heavyComputation(), but in useState(()=>heavyComputation())
, JavaScript will not run heavyComputation(), but will pass in the curried function, and useState knows not to rerun this function.
Render 1: useState(heavyComputation()) //JavaScript calls heavyComputation
Render 2: useState(heavyComputation()) //JavaScript calls heavyComputation
Render 3: useState(heavyComputation()) //JavaScript calls heavyComputation
...
Render 1: useState(()=>heavyComputation()) //useState() calls heavyComputation
Render 2: useState(()=>heavyComputation()) //useState() uses the value from the previous render so heavyComputation() is not called
Render 3: useState(()=>heavyComputation()) //useState() uses the value from the previous render so heavyComputation() is not called
...
When we have some heavy computation to initialize the state, we should use the function. And this is lazy initialization of the state. Here is a well-written blog on react state lazy initialization by kentcdodds.
© 2022 - 2024 — McMap. All rights reserved.