Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why React needs another render to bail out state updates?

Tags:

reactjs

Consider the following Component

const Component = () =>{
    const [state, setState] = useState(null)

    const onClick = () => setState('foo')        

    console.log(state)

    return <button onClick={onClick}> Change </button>   
}

Edit sad-thompson-s3l3i

  • Before pressing the button console just prints null
  • First time button is pressed console prints foo
  • Second time button is pressend console print foo
  • Third time and forward console doesn't print anything

I understand that console doesn't print anything cause I'm calling setState passing the same value as the current state and React is bailing out the state update. My question is about the following assertion

Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go “deeper” into the tree. If you’re doing expensive calculations while rendering, you can optimize them with useMemo.

Why is this extra render necessary? I mean, Isn't Object.is returning false since the second click?

like image 781
Dupocas Avatar asked Oct 02 '19 20:10

Dupocas


People also ask

Why should states not be updated directly in React?

React will then look at the virtual DOM, it also has a copy of the old virtual DOM, that is why we shouldn't update the state directly, so we can have two different object references in memory, we have the old virtual DOM as well as the new virtual DOM.

Does React re-render if state changes?

As we already saw before, React re-renders a component when you call the setState function to change the state (or the provided function from the useState hook in function components). As a result, the child components only update when the parent component's state changes with one of those functions.

What happens when state is updated in React?

This is a function available to all React components that use state, and allows us to let React know that the component state has changed. This way the component knows it should re-render, because its state has changed and its UI will most likely also change.

Why does React render multiple times?

You can see in the console tab, that the render lifecycle got triggered more than once on both the app and greeting component. This is because the React app component got re-rendered after the state values were modified, and it also re-rendered its child components.


2 Answers

Internally useState is a useReducer, with a basicReducer, The hooks uses a queue of changes in order to update the states.

AFAIK after looking the code it is a condition where the memoizedState is not fully processed in the queue, because is no using the fine control of the hook useMemo

like image 164
osdamv Avatar answered Nov 13 '22 14:11

osdamv


I got a satisfatory answer from a deleted answer in this same question. d.c pointed that Dan Abrahmov gave an answer in this old github issue. Quoting Dan:

I think at the time we decided that we don't actually know if it's safe to bail out in all cases until we try render again. The "bailout" here means that it doesn't go ahead to render children. But re-running the same function might be necessary (for example, if a reducer is inline and we don't know if we bail out until we re-run the reducer on next render). So for consistency we always re-run it on updates during the render phase.

like image 39
Dupocas Avatar answered Nov 13 '22 16:11

Dupocas