7

I've noticed a couple of ways of achieving seemingly the same thing inside a React functional component. When you have what is essentially a config value that is only needed inside this component (Just a constant value, never passed in or modified) You could just use a regular const or you could store it in the component's state.

Standard variable:

function Example1() {
  const a = 1
  return <div>{ a }</div>
}

Stored in state:

function Example2() {
  const [a] = useState(1)
  return <div>{ a }</div>
}

I get the impression that behind the scenes this would lead to Example1 creating a variable on each render and then disposing of it, while Example2 will create the variable once and maintain it until the component is unloaded. Is that accurate? And is one of these methods preferable in terms of performance/good practice?

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
DBS
  • 9,110
  • 4
  • 35
  • 53

3 Answers3

9

Is that accurate?

Yes, as you said, Example1 creates a variable on each render (marking it as "disposable" in the end of the scope - not related to React but Javascript), Example2 creates the variable once and maintains it until the component is unmounted (or the state of this variable changes via setState).

And is one of these methods preferable in terms of performance/good practice?

As a good practice - Example1.

As for performance, it should be Example1. Example2 runs useState and compares the value a with the previous state on every render which is "much more expensive" than declaring a variable.

A better example will be comparing component reference/memoized variable vs. variable (Example1):

function Example2() {
  const a = useRef(1);
  const b = useMemo(() => 1, []);
  return <div>{a.current} , {b}</div>
}

But the answer remains almost the same.

Seeing such code indicates that the ref a might change. The use of useMemo indicates that b is a "heavy computation" variable, if not, it's just an overhead (same explanation as above) and better use Example 1.

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • What is considered a heavy computation here? If, for example, the value of the variable is calculated by passing a prop to a function that switches over that prop and then returns a value, is it considered a heavy computation? If not, could you give a an example? – Amin Dannak Jul 04 '21 at 05:55
  • 1
    Heavy computation is when you get a render lag without memoizing it. – Dennis Vash Jul 04 '21 at 10:49
5

Keeping focus of this answer on when to use what.

Basic concept,

  • If you need to watch on a value and react on it, storing it in state makes sense.
  • If you just wants to store a value for display/calculation purpose, using a const/let is more appropriate.

Now in your second example

const [a] = useState(1)

This line of code is straight up wrong. Thats because you are adding a watcher but not accepting the setter callback.


Example1 creating a variable on each render

Yes this is correct. In Example2, it creates 1 variable, however, a state in React is immutable. That means, every render, the entire object is copied to a temp variable, destroyed and created again. Due to this fact, its adviced not to store huge objects in state as it will have adverse effect on your performance.

Rajesh
  • 24,354
  • 5
  • 48
  • 79
  • Hmm, interesting. When you say Example2 is wrong, is that purely from a "This is pointless as it's never modified" perspective, or would it actually cause any issues? I found that example in bit of code that was fully functional and working as expected so I got the impression is was valid (Which made me ask the question in the first place, wondering if it was in some way better than the `const` I was using beforehand) – DBS Mar 23 '20 at 17:27
  • @DBS Its not technically wrong. But when you add value to state, react provides you a setter and puts a watcher on this variable. If you do not accept setter/ use it, you are wasting resources. Also, state is a part of React's lifecycle. If a variable has static value, my suggestion is to define it in config or outside component, so no extra variable will be created. But putting in state is kind of conceptually incorrect place – Rajesh Mar 24 '20 at 05:59
  • you say: "a state in React is immutable. That means, every render, the entire object is copied to a temp variable, destroyed and created again." Why is that so? How the fact that state is immutable makes it so the object is copied, destroyed and created on each render? Perhaps you could point me to a doc that says so – mallocthePD Jul 18 '21 at 13:30
1

Your assumption is almost right, with useState the variable is create once and reused on every render.

However, the main difference is that modifying a variable created with useState (via its setter method) triggers a component refresh.

If you just need to save a value between renderings you should use other hooks, e.g. useRef, useCallback or useMemo

Daniele_s
  • 116
  • 1
  • 2