React — re-render vs re-evaluation issues with ease!!

Rajesh Kumar
11 min readMar 22, 2022

In this article, we will understand the very basic but most important topic of React. Most of the time learners do not have deep knowledge or clarity about re-rendering and re-evaluation and sometimes they think that these two are the same thing. But it is not true !!

To understand these two different terminologies let’s first look at how React normally works in the background with normal flow.

How does React work?

As a general definition React is a JS library for building user interfaces.

React is all about components and we use those components to build user interfaces. Basically, by using components through effective structuring we build the user interface and also update the user interface using components.

React does all these things (i.e. build/update UI) using ReactDOM concepts. You can know in detail about ReactDOM or Virtual DOM through my other article: Do You Really Need React-Js? WHY?

ReactDOM is act as an interface to the Web because React itself doesn’t know the web. React directly deals with how to work with components but it doesn’t care whether those components contain HTML elements or if they contain totally fictional elements. It’s ReactDOM to which that matters in the end and which ultimately needs to bring real HTML elements to the screen.

React is just a library that manages the component, data, states, and detects how the components may need to be changed, and then delegates all the information to the ReactDOM and then to update or add new changes to the UI, ReactDOM works with the web browser actual DOM.

Below you can find illustrated representation to connect the theoretical written line in a more easy way.

Now we understand how to React works in general and how React DOM is responsible for UI visualization. So it’s time to understand the re-evaluate and re-render.

Re-evaluate and Re-render!!

As we understand React is only concerned about context, props, state, component, and other built-in properties. So whenever a component’s State, Props, Context, or other built-in properties change, function[component is nothing but a JS function] re-executed, and that component is Re-evaluated by React from top to the bottom.

After the re-evaluation updated info passes to the ReactDOM, then ReactDOM virtually compares the new changes with the previous/existing cloned data then if ReactDOM finds out any differences then it Re-render that specific real DOM element or DOM Value with the new element or value.

Let’s summarize the above-illustrated iteration.

So whenever we run our React app for the first time it will execute the function component and do evaluate all present states, props, context, etc. as mentioned in step-1, and then React passes the info to React DOM to display the component on the Real DOM web screen. Once the information is passed to the React DOM, it will virtually compare the difference with real DOM. As it’s the first time so every info is new so after virtual comparison it will add all new elements to the DOM and render the UI for the first time.

Now suppose if we will perform some action [button click, hover, etc.] which will update any state or props or context of the component, in that case, the function component will again re-execute[as we have learned earlier] and re-evaluate the component from top to bottom and then will pass the info to ReactDOM as mentioned in step-2 & step-3. Then ReactDOM will virtual compare the info and if there will be changes in DOM element or DOM element value, it will re-render that specific DOM element or value only but if there are no changes in DOM element or value because of re-evaluation then re-render will not happen as mentioned in step-4 & step-5.

— — — — — — — — — — — NOTE — — — — — — — — — — — — —

Real DOM doesn’t change all the time. It changes rarely and only when needed. That’s important for performance because making virtual comparison b/w the previous state and current state that’s fairly cheap and easy to do that happens in memory.

But Reaching out to the real DOM, that is rendered in browser is pretty expensive from a performance perspective because it’s intensive task [Of course not for tiny changes at one place but tiny changes in multiple place in complex or big project] and your page might become slow.

If we don’t handle re-evaluation properly then it can cause problems which will lead to a bad user experience and bugs. 🤯

So let’s understand that problem of the re-evaluation and re-rendering with a simple react app!! :)👌

Let’s build a very simple demo React app. In which we will display name text, welcome message text, and a button. By default, the welcome message text will be hidden but when we click on operation via button it will toggle message [i.e. hide and Un-hide] as shown below:

You can find the code for the component that is responsible to display the above UI.

P.S~ Don’t expect code optimization in the sample app, as our focus is only on understanding the concept.!!😉

Let’s summarize the code to understand the code logic and flow of execution. I have created two function component file names as App. js[Parent ] and Greeting.js [Child]

inside app.js file, added console statement at top of the function to print “app component” in-browser console [included the console, because it will print the message in browser console through which you can see the function call easily] and having a state property show which passes to the child Greeting child component and also having click event handler functiontoggleMsg which will be invoked when we click on Show/Hide Message Button to toggle the value of state show .

then it returns HTML element text “HI John” , a child component <Greeting/> to display the message and a Button to toggle the message.

Inside Greeting.js, added console at top of the function which will print “greeting component” in the browser. this component is accepting props showMsg from its parent component [In this case App.js] then returns the text element “Welcome to XYX pvt. Ltd.” if the value of props.show will be true else not return that element.

Let us now understand the flow of UI :)

When you will be running this project for the first time, it will execute the root component App and will execute it from the top to bottom. In App.js it will encounter console.log(“App Component”) as a first-line so it will print it in the browser console then state initialization will happen {show: false}. that after it will encounter function declaration toggleMsg(){..}to update the state value upon clicking on the button, as that is only the declaration so that function so nothing will execute inside the function. once all execution is completed before return then the function will return the elements “Hi John” <Greeting/> and button.

As we are passing the props showMsg={show} to the child component <Greeting/>, so then function component greeting will execute from top to bottom, where it will encounter console.log(“Greeting Component”) as a first-line so it will print it in the browser console and then it will return the element text “Welcome to XYX pvt. Ltd.” if received props {showMsg : true} but initially, it is false so the text element will not display anything in the UI(i.e. msg will be hidden).

Once all execution of parent and child components is has completed, React will pass the information to ReactDOM where it will virtually compare the new info with virtual DOM of real DOM element, as it’s the first time so it will render all the data to the real DOM of browser and we can able to see the UI.

Now suppose you want to display the greeting message “Welcome to XYX pvt. Ltd.” so for that value of state show should be true. To change the value of the state show you have to click on the button “Show/Hide Msg”, then onClick will call the toggleMsg() function where it will update the state of {show: TRUE}, from false and we know whenever there is any change in state, props, context, and its internal data properties, the component will re-execute the function and re-evaluate from the top to bottom. So after updating the state value again it will execute the App function as we mentioned above.

Then after re-evaluation of function, it will again pass the info to React DOM where it will compare with previous Virtual DOM with new data, and in this case, it will encounter that props.showMsg==TRUE that’s mean a new text element “Welcome to XYZ pvt. Ltd.” will get added to the real DOM and then React DOM will re-render that specific DOM element position only not the whole DOM element to display the greeting text.

Now it’s time to understand the issue with re-evaluation if we will not handle it properly.

I. Unnecessary Re-execution of the child component

So let’s do a little modification in App.js to understand this issue.

<Greeting showMsg={false}/>

Earlier we are passing state show as a dynamic value prop to the <Greeting/> component but now we have modified and passed static Boolean value false, which means “Welcome to XYZ pvt. Ltd.” will not display ever on the UI as it will always be false.

So if you will click on “Show/Hide Msg” button, so it will invoke the toggleMsg() function and will update the state value of the show, that’s mean it will again re-evaluate the parent component (App.js)and child component (Greeting.js) as the state has updated for the parent component.

But as we are passing the static Boolean value of showMsg=false to Child component that’s mean <Greeting/> should not be re-evaluated as there is no need to re-evaluate again, but because of update of the state show in the parent component, everything will be re-evaluated from top to bottom, Greeting Component will be also re-evaluating and React DOM will virtually compare with virtual DOM as it is the part of parent component but re-evaluation and virtual comparison is unnecessary.

For this Small react App it’s not an issue but suppose we have the real-world complex project where there are multiple nested child components and if we will not handle this case then it will re-evaluate all nested children which can lead to the Performance Issue. 😢🤦‍♂️

Now you are thinking that is there any way or solution to handle this issue to avoid unnecessary re-evaluation and how? 👼

Yes!! if we have the solution for this to handle. We can handle it using the concept of React Memo.

I have not covered the memo in this article as the focus of the article is the concept of re-rendering and re-evaluation only.

I have written a separate and well-explained article on React Memo that is the continuation of this article. You can refer to the article to learn about this topic.[…coming soon]

II. Re-evaluation leads to other issues Function re-creation

Again did a few modifications in the existing React app to understand this issue.

Created one more new Custom function component named as Button.js. which will wrap the HTML button component like below:

And then I have imported the <Button/> component and replace all the button HTML code with this Button Component and pass the function toggleMsg() as toggleHandler props to this Button component inside App.js like mentioned below to use it as a child component. other than that everything will be the same as previous.

There is no change in UI, just create one more functional component to explain the issue of function re-creation because of re-evaluation.

Since now Button is also a child component of App.js so when state show change Button will also re-evaluate and re-execution will happen for <Button/> component.

You are thinking that I have already mentioned that we can handle it using React memo why I’m explaining the same thing again? 👵

But that solution will not work here because here we are passing function not the dynamic primitive value like show or a static primitive value true .

But the function is a Reference value not primitive!!! As we have studied in JavaScript if we re-execute any Reference values then it will create a new instance reference for every new execution or run.

— — — — — — — — — — *IMPORTANT* — — — — — — — — -

Please do refer my article to understand the concept of primitive and reference in depth with ease : Reference Vs Primitive

Once you understood the reference and primitive then only you will be able to understand this concept without any difficulties.

As for re-execution, a new function object reference will create for every execution so we cannot handle it using React memo because as we know that through React memo we do inform React that, only re-evaluate the child component once its props value will change!! and as in this case function reference changes on every re-execution so <Button/> component will also re-evaluate which is again unnecessary.

Again for this Small react App it’s not an issue but suppose we have the real-world complex project where there are multiple nested child components and if we will not handle this case then it will re-evaluate all nested children which can again lead to the Performance Issue.

Now again you are thinking that is there any way or solution to handle this issue also to avoid unnecessary function re-creation and how? 👼

Yes!! if we have the solution for this as well to handle it. We can handle it using the concept of React useCallback. You can refer to the article to learn about this topic.

I have not covered useCallback in this article as the focus of the article is the concept of re-rendering and re-evaluation only.

I have written a separate and well-explained article on React useCallback that is the continuation of this article. You can refer to the article to learn about this topic […coming soon].

That’s how re-rendering, re-evaluation flow works and if we will not handle the mentioned case then we will land into unnecessary re-execution and function re-creation as explained!!😃

I hope all of your concepts have been cleared!!! If you really liked this article click the clap 👏 button below. Also, write your feedback and queries in the comment section.✍

--

--