BFE.dev solution for React Quiz
1. React re-render 1
1. Initial render(mount)
Let's look at what happens step by step.
const root = createRoot(document.getElementById('root'))root.render(<App />)
This render()
call kicks off the rendering of whole app.
It first see <App/>
, so App()
is run and "App"
is logged.
function App() { return ( <div> <A state={state} /> <D /> </div> )}
Keep in mind that components are blueprints, child components are not rendered directly, but that React runtime renders the children in a synchronous or asynchronous DFS-like approach based on the priorities of tasks it has internally.
When App
is rendered, React sees following children that needs to be rendered further.
<div> <A state={state} /> <D /></div>
React then goes to <div/>
→ <A/>
, so A
is run and "A"
is logged.
Similarly React goes to <B/>
→ <C/>
, in the end <D/>
is processed.
When all components are rendered and the changes for DOM are committed, this marks the whole journey for the initial render(mount).
So far we get following logs.
'App''A''B''C''D'
2. Re-render
Once initial mount is done, React tries to flush the passive effects(useEffect
)
in component App
.
const [state, setState] = useState(0)useEffect(() => { setState((state) => state + 1)}, [])
App
holds the state
, when setState
is called, it does NOT update the state
immediately but schedules an update internally which tells React that App
needs
to be re-rendered, and by incrementing the state by 1.
One thing to keep in mind is that on any state updates, React basically tries to re-render everything from root, while it skips rendering components that doesn't receive updates, or even skips the whole sub-tree if there are no updates there.
Check out how
useState
works internally. and how bailout works in React
So React start re-rendering everything from root, which is App
. App
is already marked
as "needs update", so App is re-run and "App"
is logged.
Now App
returns a new set of children.
<div> <A state={state} /> <D /></div>
div
receives new props, becausechildren
changes.A
receives a newstate
(actuallystate
doesn't matter)D
receives a new empty object{}
for props.
This might doesn't look obvious. It is much easier to understand if we re-write the JSX into object notation and notice that this is a new object being returned every time the function is run.
{ type: "div", children: [ { type: A, props: { state: state } }, { type: D props: {} } ]}
Even state
doesn't change, once App
is re-rendered,
A
and D
always get new object for props.
So now React have to go further to to <div/>
because it has updates in props.
React renders A
, B
, C
and D
for the same reason and we get following logs,
as the result to the question.
'App''A''B''C''D''App''A''B''C''D'