How to debug a React application when component is rendered multiple times? - reactjs

I am new to React. I noticed that when components in my application render, line simple two dropdowns, even, in this case, breakpoint hits 15-16 times because of the re-rendering. I need to know where should I place my breakpoint or what should I log to console.log each time, so that I'll come to know why the component is rendered, like can I log a particular attribute or state variable?

Yeah, debugging React apps using breakpoints can be a pain because of all the under the hood React work you may have to step through. Yes, console.log can be super useful, and you should check out React Devtools as well.

Put console.log as the first line of the render function starting with a few of the highest level components. They probably don't rerender much.
Work your way down the tree until you find the culprit.
Many times the effect is multiplicative. One component rerenders 5 times and one of it's children rerenders 3 times per parent render will mean 15 rerenders for everything south of that child.

Related

In React, is it possible to memoize a list of components and their internal state?

[This is the Codesandbox with all of the code that exemplifies the issue I'm having. Sorry, SO doesn't allow for proper React code with TSX, etc.]
I have some tabs, naturally, whenever I click on each of them, my state changes (namely selectedTab) and the body that's being rendered. Each tab item has a body that goes with it, the first tab, in my case, has a component that, if you click, a count is increased. Well, whenever the tab changes, that count gets reset. In fact, it's a full-rerender all around.
The problem with doing a full re-render is that - not only is it inefficient, given how the user's gonna use it, but it also adds fuel to the fire: what if the user inputs something on a tab, then switches to another tab to do something else and then back to the original one? He's just lost what he typed in.
Naturally, this can be solved if we render all of the tabs' content upfront and we just play with display: none, and it'd be a good solution, but I'm also trying to learn.
I understand how React re-renders things and why this happens, but is there a way to fix it?
In my case, if you look at useTabs, the content variable simply looks at the corresponding tab's component key and takes outputs that. It's there that, I think, I need to memoize things.
Uhm, I guess you can't prevent calling your custom hook, this will lead to invariant violation error.
These hooks in the component will be executed on each render -> thus 'resets' your tabs.
You should rely on useEffect dependencies argument to run conditional code to see if values needs to be changed.
as long as your in the same app you could use contextApi,react context docs otherwise you can use localstorage, localstorage tutorial
or just create this state in the parent component and pass it down as props?

React Native how to use React.memo on every component from collection to render only changed ones. Strange behavior of React.memo

I have been trying to improve rendering performance by using React.memo on components. It works properly until I use it on every single component from the collection being inserted as children.
I prepared snack HERE
To understand what is going on you need to open the console because there are some logs presented.
You will see WrapperMemo which generally renders Child components (they are also wrapped in some auxiliary components to check something I will explain later).
When you press the first button named SLICE MYNUMBERS you will see that React.memo's isEqual function called isWrapperEqual returns true, but it still does not stop from rerendering Child components.
However neither Wrapper nor all other auxiliary wrapper components (ChildOk) are rendered!
When you click any PRESS ME:[number] button it forces you to re-render other Child components when only one is being modified.
It is worth mentioning that TestCompMemo is never re-rendered when any of the buttons are pressed - which is correct behavior.
1) Is there any explanation for that?
2) Is there a way to use React.memo on every component from collection to render only changed ones (as it is presented in Wrapper component) ?
Is there any explanation for that?
In your snack example, you have a Context.Provider wrapper at the top level of the application.
This is what causes the re-render. This is expected behavior and you can read more about it here: https://github.com/facebook/react/issues/15156#issuecomment-474590693
Is there a way to use React.memo on every component from collection to render only changed ones (as it is presented in Wrapper component) ?
Using React.memo on every component is not recommended. You can run into bugs where components do not re-render and you are adding overhead with all the comparisons.
If you want to optimize the application, you might want to run the profiler and figure out which parts of the app is slowing things down and work from there.
But if you want to prevent unnecessary re-renders, you could move context usage up a few levels and pass the onPress to the child components.

How is Virtual DOM updated?

Imagine that you've built an application with ReactJs containing a hundred elements. Let's say that in some time, the state of component A changes, and for the sake of simplicity we assume it has only one element and no child component.
My question is: how is Virtual DOM updated in response to the state change?
After a few hours of research, I found two contradictory opinions:
The entire Virtual DOM is torn down; then it is rebuilt from scratch
Only the changed elements are updated in the Virtual DOM.
Unfortunately, official documentation is not clear about this. So, can anybody give the correct answer? (please with supporting reference)
[Edit] : Some parts are imcomplete here, think about reading the comment section !
React update a component when its state or a prop changes. It does a comparison between the previous JSX and the new one and re-render only the differences.
If the parent component has its state or a prop changed, it will be updated.
The child will not be refreshed unless a prop from the parent that is passed to it changes.
Note that the useEffect from the child is triggered first. Knowing that, If you do things that update the state in the child component, then it will be re-rendered everytime (Because the usEffect is triggered everytime if you don't set any dependencies).
Test from Stackblitz - Child Effect is triggered first
Article that made me notice it (I didn't know before this answer :D)
Here is how I understand things in React. To be short, the entire virtual DOM isn't rebuilt from scratch, it's not how JSX comparison works.
I don't have much sources about what I said, but here is the explanation about jsx update from the official documentation. Just that should be enough to eliminate the first point of your list.

React lifecyle: phases

As much as I know, this are the "phases" on a react lifecycle for a component:
Mounting: Mounting is the stage of rendering the JSX returned by the render method itself.
Updating: Updating is the stage when the state of a component is updated and the application is repainted.
Unmounting: As the name suggests Unmounting is the final step of the component lifecycle where the component is removed from the page.
mounting -> updating -> unmounting
I succesfully used it, but i don't know how to mix those 3 "phases" with :
- commit phase
- precommit phase
- render phase
I found this : http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
I'm not sure if "mounting", "updating" and "unmounting" are phases or somethings else. Can it be the case that phases are: commit, precommit and render. And "mouting, updating and unmounting" are events or stages ?
Any clues?
The "render phase" and "commit phase" are descriptions of the internal process that react goes through to update your page. While it can be useful to understand what's going on in these, the only place you can interact with it is through the various lifecycle hooks, such as componentDidMount, componentDidUpdate, and componentWillUnmount, so those are the things i would recommend you focus your research on.
When it's time to render the page (usually caused by calling this.setState somewhere), react goes through a series of steps in order to update the webpage:
The first group of steps are collectively called the "render phase". In the render phase, react is creating the Virtual DOM. In other words, it's determining what the page is supposed to look like, without actually changing the page. In the simplest form (where we're not skipping any renders with things like react.memo or shouldComponentUpdate), react calls render on the topmost component, and finds out what it returned, and then for each of its children it calls render on those as well until it knows what the whole page should look like.
The second group of steps are called the "commit phase". Now that it knows what the page should look like, it needs to update the actual DOM to match the Virtual DOM. To do this, it compares the current virtual DOM that it got from the render phase with the virtual DOM it got the last time it rendered, and figures out the minimum set of updates in order to make the page look like that.
And now the rendering is done and the page has been updated. During this process it's possible that some components got created for the first time (ie, "mounted"), or they got their props changed (ie, "updated"), or they were removed entirely ("unmounted"). Components that had this happen to them will have their componentDidMount, componentDidUpdate and componentWillUnmount functions called as appropriate.
Render phase: Is used to calculate changes, and may be aborted if the user wants to. If this phase is aborted the DOM isn’t updated.
Pre-commit phase: Is a period where you can read changes made to the VDOM, before they are applied to the actual DOM.
Commit phase: Here the changes are applied and any side effects are triggered.
Mounting: Runs once when the component is created.
Updating: Runs each time a change is made to the component.
Unmounting: Runs once when the component is about to be destroyed.
Have a look at this article for details
https://medium.com/#vmarchesin/the-react-lifecycle-step-by-step-47c0db0bfe73#:~:text=Pre%2Dcommit%20phase%3A%20Is%20a,any%20side%20effects%20are%20triggered.

React Js Performance

I am using react(V0.13.3),flux(V2.0.3)
I have a component that has many inner components.
While the inner component getting updated, the browser is going off. I am unable to scroll click and some time I get a pop up saying:
unresponsive script would you like stop.
I am following all React life cycle methods and implementing the shouldComponentUpdate method.
I think the DOM Diffing is eating so much CPU time and RAM allocated to the browser.
Any idea about why I have this issue and how I could get out of it?
Reactjs can easily go into endless render cycles. Let's say you put a method that pulls Data from the server in componentDidUpdate and it mutates the reducer that is used by a parent Component. Boom. The component tree rerenders. Your shouldComponentUpdate may be useless bc the input is not the same reference. And the server gets hit again. Endless loop.
The solution is to use guards. When you hit your componentDidUpdate (or wherever you hit the backoffice) method for the first time, the method that mutates the reducer should set a kind of IsLoading variable on the reducer. you check this variable to see if you should fire off your mutating request again. This guards against needless rerenders

Resources