When React functional component re-render, does it reassign assigned values & functions?
Asked Answered
C

3

14

If a code like this re-render by useEffect's dependency,

// ...
const Test = () => {
  // ...
  
  const value1 = "test1"
  
  const func1 = () => {
    // do something1
  }
  
  useEffect(() => {
    const value2 = "test2"
  
    const func2 = () => {
      // do something2
    }
  }, [sth])
  
  return (
    // ...
  )
}

does value1 & value2 & func1 & func2 reassign to memory?

I'm curious about it, related to optimizing.

Cryptonymous answered 4/3, 2021 at 3:54 Comment(0)
M
7

does value1 & value2 & func1 & func2 reassign to memory?

in short the answer is yes.

it's more clear if you look at it for what it is: Test is a function, so everytime that function is called all the variables inside the function scope (the curly brackets) are re-declared and re-assigned.

Let's dive into the details:

value1 and func1 are in the function's body so they get declared and assigned every time the function is called, they are not related at all, they have just the same name.

value2 and func2 instead are declared inside an useEffect hook with a declared dependency (sth), this means that these 2 variables are redeclared and reassigned only after the first render and after every other render if the sth variable changed its value compared to the previous render.

if you want to optimize value1 so it doesn't change at every render you can use the useMemo hook this way:

const value1 = React.useMemo(() => {
  return "test1"; //here you might have a more complicate way to determine value1
}, []); //array of dependencies like for `useEffect`, so `value1` will be recalculated only if any of the values provided in here change. by leaving it empty value1 will always be the **same** variable

you can do similar optimizations with functions too with the useCallback hook

Markswoman answered 4/3, 2021 at 4:27 Comment(0)
O
12

Short answer, yes. Every time the function runs the old values will be garbage-collected, new primitive values will be assigned in memory and new references will be created to functions and objects.

But the real question with a "not-that-short" answer is "does it impact performance in a significant way?". And the answer is... depends. In most cases, it will not (see the doc about it). But there are scenarios where you will need to make some changes to have a performance optimization with useCallback and use useMemo.

It's also worth mentioning (as said in Shivam Jha's answer) that a trigger in useEffect no necessarily causes a re-render (DOM paint) because this process happens first on the virtual DOM and will only be persisted in the real DOM when necessary.

I will leave here some other references about this discussion.

Dan Abramov's tweet on memoizing everything (also look at responses)

Kent C. Dodds's article about render performance

Felix Gerschau's article about when render occurs

Obscuration answered 4/3, 2021 at 4:9 Comment(0)
M
7

does value1 & value2 & func1 & func2 reassign to memory?

in short the answer is yes.

it's more clear if you look at it for what it is: Test is a function, so everytime that function is called all the variables inside the function scope (the curly brackets) are re-declared and re-assigned.

Let's dive into the details:

value1 and func1 are in the function's body so they get declared and assigned every time the function is called, they are not related at all, they have just the same name.

value2 and func2 instead are declared inside an useEffect hook with a declared dependency (sth), this means that these 2 variables are redeclared and reassigned only after the first render and after every other render if the sth variable changed its value compared to the previous render.

if you want to optimize value1 so it doesn't change at every render you can use the useMemo hook this way:

const value1 = React.useMemo(() => {
  return "test1"; //here you might have a more complicate way to determine value1
}, []); //array of dependencies like for `useEffect`, so `value1` will be recalculated only if any of the values provided in here change. by leaving it empty value1 will always be the **same** variable

you can do similar optimizations with functions too with the useCallback hook

Markswoman answered 4/3, 2021 at 4:27 Comment(0)
B
1

According to docs:

What does useEffect do? By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.

Also, it does not re-renders the code but runs the code again when the dependencies passed to it changes

Tip: Optimizing Performance by Skipping Effects describes solving performance problem due tocleaning up or applying the effect after every render.

Also, you can free up allocated memory (if not freed automatically) or run some side effects after running the code (setTimeOut, etc) by using useEffect with cleanup. Basically do everything you want to run after useEffect inside a return function:

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
Brass answered 4/3, 2021 at 4:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.