What is useState in React?
useState is a React hook that allows functional components to manage and update local state.
But you have to make sure to update the state through useState()
, not directly mutate the state
itself.
Basic Example of useState
const [count, setCount] = useState(0);
setCount(count++)
console.log(count) // 1
The Problem with object
state in useState
Javascript has two places where it can store the data: stack
and heap
, and it relates to the story of primitive values
and references
.
primitive values
and references
stack
is used in Javascript to store static data such as primitive values
(strings, numbers, booleans, undefined, and null) in which the size of the data is fixed, while
heap
is used to store the dynamic data such as references
(objects and functions).
The values of primitive values
are simply stored in the stack
that's it, while the content of references
itself is stored in heap
referenced from the stack
.
This creates a situation where a newly assigned value that references the existing object is interpreted as identical.
Lets's look at an incorrect example👺:
const [state, setState] = useState([1,2]);
const temp = state
temp.push(3)
useState(temp)
Because temp
and state
both reference the same values in the heap, they are effectively identical. This violates the rule of useState, which requires a new object or value to trigger a re-render. 😇
How to solve it?
⛩️⛩️⛩️⛩️⛩️⛩️⛩️⛩️⛩️⛩️⛩️⛩️⛩️
Spread Syntax
[...[]]
helps you create a separate copy of the value in heap
.
const a = [1,2]
const b = a
console.log(Object.is(a,b)) // true
const c = [...a]
console.log(Object.is(a,c)) // false
voila 😀
const [state, setState] = useState([1,2])
const temp = [...state].push(3)
setData(temp);
Now, the value temp
is different from the original object, ensuring that it no longer shares the same reference as state.
Another pitfall in-place
function
The in-place
functions such as sort()
modifies the data in place, without creating a separate copy of the data structure.
a = [1,3]
a.sort((b,c) => c-b)
console.log(a) // => [3,1]
As you can see, the values in a
has changed.
Again here is an incorrect example👺:
const [state, setState] = useState([])
const sortOrder = () => {
state.sort((a, b) => a-b)
setState(state);
}
state is mutated against the rule. 😇
So here is the solution with spread syntax.
const [state setState] = useState([])
const sortOrder = () => {
const newState = [...data].sort((a, b) => a-b)
setState(newState);
}
but wait, before reaching to the conclusion with spread syntax
, remember to look up the documentation to to catch up the latest updates.
Check a document
There is a chance that the functions is updated.
For example, toSorted()
is newly introduced in 2023 that returns a copying version of the input data 🌅
const [state, newState] = useState([])
const sortOrder = () => {
const newState = state.toSorted((a, b) => a-b)
newState(newState);
}
AI is not good at catching up the latest information so this traditional methodology is still worth it!
Conclusion
Let's use spread syntax [...[]]
but remember to consult the documentation as well.
Reference
https://felixgerschau.com/javascript-memory-management/
https://react.dev/reference/react/useState
Top comments (0)