Why React Hook useState uses const and not let
Asked Answered
F

7

80

The standard way to use a React useState Hook is the following:

const [count, setCount] = useState(0);

However this const count variable is clearly going to be reassigned to a different primitive value.

Why then is the variable not defined as let count?

Factor answered 14/11, 2019 at 15:12 Comment(2)
If you change the state, the component will clearly re-render right? So if it re-renders count will never be "reassigned"Salami
Indeed, in the scope of the function count remains inmutable. Thanks Kevin!Factor
D
88

clearly going to be reassigned to a different primitive value

Not really. When the component is rerendered, the function is executed again, creating a new scope, creating a new count variable, which has nothing to do with the previous variable.

Example:

let _state;
let _initialized = false;
function useState(initialValue) {
  if (!_initialized) {
    _state = initialValue;
    _initialized = true;
  }
  return [_state, v => _state = v];
}

function Component() {
  const [count, setCount] = useState(0);

  console.log(count);
  setCount(count + 1);
}

Component();
Component(); // in reality `setCount` somehow triggers a rerender, calling Component again
Component(); // another rerender

Note: Hooks are way more sophisticated and are not actually implemented like this. This is just to demonstrate a similar behavior.

Demetriusdemeyer answered 14/11, 2019 at 15:14 Comment(6)
GREAT ANSWER @Felix Kling. When react re-renders the component then, the functions are re-created (new scopes are created) that DO NOT HAVE ANY LINK WITH THE PREVIOUS FUNCTIONS (with the previous scopes) created in a previous render, is that right?Hectorhecuba
hi @Felix Kling +1 awesome, when people say that the state is considered immutable (talking about function component, of useState(), and not class components obviously) it is also because of this, isn't it?Dosi
@GeorgeMeijer: That's right.Demetriusdemeyer
@Daniel: Possible, but they might also refer to the fact that you should create a copy of an object or array when they are stored in state and you want to change them. I.e. setList([...list, newElement]) and not(!) list.push(newElement); setList(list);.Demetriusdemeyer
great @Felix Kling thanks, the previous scopes just get lost, they go to the garbage collector, they are unreachable,right?Hectorhecuba
@GeorgeMeijer: Only if nothing else is referencing it. E.g. the component could contain a useCallback hook whose callback doesn't change on every render. At any time the component is rendered, the callback might not change and instead the callback from a previous render is used, which of course will somehow hold onto the previous scope/execution context.Demetriusdemeyer
G
11

const is a guard against reassigning the value of the reference within the same scope.

From MDN

It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.

Also

A constant cannot share its name with a function or a variable in the same scope.

Gertiegertrud answered 14/11, 2019 at 16:8 Comment(1)
Primitive values are immutable though, so the question is more about explaining how come a const number can change?Okubo
G
4

It's not exactly assigning a new value. useState is simply a state updating function. Const is used here because the change of value is being managed somewhere else by React. You're telling React to manage some value for you by calling useState.

Glacial answered 12/8, 2021 at 10:42 Comment(0)
F
2

After calling setCount the component is rerendered and the new call of useState returns the new value. The point is that count is immutable. So there's no typo here.

Technically it is a new variable at every render.

Source: React Github issue: Docs - Hooks: is that const a typo ?

Fenrir answered 14/11, 2019 at 15:15 Comment(0)
T
0

here I found that const was frustrating since count needs to change so

  let [count, setCount] = useState(0)
  // simply can't use ++ on either side of count increment given we declare as const [count, setCount] 
  // instead declaration of var or let [count, setCount] allows simpler code
  const increment = () => {
    setCount(count++); //const cannot do this only let or var
  };
Transect answered 2/5, 2020 at 8:55 Comment(2)
count should not be modified like this... you should use setCount(count + 1); and keep the const. It is misleading because the subsequent rerender would work, but the first render would start with a value other than 0.Enchiridion
also to prevent multiple increment calls overwriting each other, you should use this: setCount((count) => count + 1)Slovenly
P
0

This has nothing to do with React.

Imaging a function

function Counter() {
  const name = 'myCounter'
  return name;
}
Counter()
Counter()
Counter()

You can call this function any number of times, right?

So is the case with React functional components, we are not assigning different values to const, we are just calling the functions and getting what they are returning.

Paragraph answered 22/8, 2023 at 14:59 Comment(0)
N
0

const [count, setCount] = useState(0);

means the variable count will now be set using the setCount function & will have its initial value as 0 during the component creation. In the same component we cant write (again) something like:

const [count, setCounter] = useState(123);

Nolan answered 6/7 at 21:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.