Lets say i have a child component that just return a div element
Child Component :
function Child() {
return <div className={styles.alertBox}>No Data Found</div>;
}
it will always re-render when the parent state change, so to prevent it re-render we will wrap it using React.memo
example :
export default function Parent(){
*some state and setState stuff*
const MemorizeChild = React.memo(Child)
return MemorizeChild
By doing that we prevent our Child Component to re-render everytime we change the state
My Question is:
did we really need to memorize the Child Component although it just return few line of html and does not execute some heavy function, because we all know that Memorizaition are not Free. in return of Time we trade space (Memory / Cache). if it not can you tell me when should i memorize my component
I would say that it doesn't make much sense to memoize such a component.
There is already a similar question, take a look.
It should be used if it's possible to quantify the performance gains from it.
Shortly I suggest using memo when:
you know that a component will render quite often
component re-renders with the same props
component is big enough to have props equality check
Also, you can use profiler to measure how often a React application renders and what the “cost” of rendering is. It can help you identify what parts of an application might need memoization.
Related
I think the fact is that, when a parent component re-renders in React, in general, all the children components re-render as well.
I did one experiment to confirm:
https://codesandbox.io/s/currying-pine-r16rzi
return (
<div>
<div>Time now is {timeNow.toLocaleTimeString()}</div>
<TheTimeNow /><TheTimeNow />
</div>
);
This parent component re-renders, and <TheTimeNow /> has no change in props value (it has none), but it re-renders anyway and shows the updated time.
I think it is not the same to say, that React actually change the DOM, as I think the mechanism is that React use the previous virtual DOM to compare with the new virtual DOM, and update only the minimal actual DOM node as on document.documentElement as needed.
This can be seen if you use Google Chrome and do Inspect Element on the time statement: only the time portion changes and the other English words stay the same. Compare to this where all the nodes changes if it is plain JavaScript: https://jsfiddle.net/8sj2ugae/1/ when you do Inspect Element.
However, can't we argue that, if a child is <Foo /> and since there is no props passed to it, then <Foo /> really should not have changed, and it is wasteful to call Foo()? (if Foo is a functional component, or call the render() method if it is a class component.)
Now since all children re-renders, that means all their children also get re-rendered. Repeat this rule recursively, that would mean the whole subtree gets re-rendered.
My question is: is it true that they should not need to re-render if their props didn't change, or are there other factors that make them needing a re-render really?
The answer is yes, there is no need to rerender. But in order to know this we need to compare a new props with a previous props. And this operation is not free.
Also if we do a shallow comparison we are increasing the probability of bugs. Someone might be expecting rerender after a deep props update.
Should React.memo be the deault behaviour? Will it improve the performance in most cases? We don't know. There is no evidence for that. More on this in Mark Erikson's post.
Here is a great article by Dan Abramov: Before You memo(). I consider two points regarding your question:
In the future compiler might decide when to memoize a component.
Component rendering doesn't mean that all it's children will be rerendered.
Here is an example:
const ParentComponent = ({ children }) => {
const [state, setState] = useState(0);
return <div>{children}</div>
}
If we update the state children will not be rerendered. React just uses a previous value. Here is an article by Kent C. Dobbs about this optimization technique.
One last thing. React.memo and useMemo are different. The first one is for component memoization and the second one is a hook for expensive calculations. There are also shouldComponentUpdate for class components and PureComponent which compare not only props but also a state.
Hopefully the answer and links will shed some light on this topic.
I have a page and part of it should be rerendered depending on a variable.
What I'm doing now is:
renderPart(){
const partComponent = (this.state.part == 0 ? <div>1</div> : <div>2</div>);
return partComponent;
}
render(){
return (<div>{this.renderPart()}</div>);
}
Every time when this.state.part is changed it's called the render function. How to make it call only renderPart function? I'm open to using any other approach but I can't figure out which it could be.
So, since your state is on the component level, every time you have a state change, the entire component will be re-rendered.
I think a good approach to solve that would be to separate this renderPart function in a new component with its own state. That way, when you have a state change, only the render function of this new component will be triggered.
If you need to share state between components, I recommend you to use redux to make it simple, maintainable, and efficient. Its better than pass states and functions to change it by props to low level components.
I'm trying to optimize the performance of app. I've found that the issue is that one of my components re-renders on a condition that I set and it contains a significant amount of data. I wanted to know if it were possible to not re-render the whole component, but to only re-render the element that has changed?
I've already tried using PureComponent, but that did not have enough control for me. I'm currently using shouldComponentUpdate.
By default every time a parent component is re rendered all the children nodes will be rendered as well, if you know for sure that a given component will always render the same content given the same props then you could turn it into a PureComponent, a pure component performs a shallow comparison obj1 === obj2 in props and only re-render when a change occurs. If you need a more complex comparison logic then shouldComponentUpdate is the way to go:
shoudComponentUpdate(prevProps, prevState){
if(prevProps.items.length !== this.props.items.length) return true
return false
}
By default this method always returns true, unless you explicitly tells it not to. The functional version of shouldComponentUpdate is React.memo. But keep in mind that comparisons take time, and the amount of processing required to perform a comparison grows with the complexity. Use it carefully.
I would suggest breaking out the piece that needs to be updated into it's own component and use React.memo or PureComponent like you were saying. This might also help.
React partial render
A basic question I need help here.
Whenever this.setState invoked at parent components, all the children components will be rendered. This will cause the performance issue if I have huge amount of child components.
Lets give an example,
Parent Component
handleToggleTick() {
const newObj = Object.assign({}, this.state, { iconName: ''});
this.setState({
iconName: newObj.iconName,
});
}
render() {
return(
<ChildComponentA iconName={this.state.iconName} toggleTick={() => this.handleToggleTick}></ChildComponentA>
<ChildComponentB></ChildComponentA>
<ChildComponentC></ChildComponentA>
)
}
Based on the example above, whenever handleToggleTick invoked from childcomponentA, setState invoked for new iconName. What I want is, only ChildComponentA only the one get render since props.iconName is related to it, but not for childcomponentB and childcomponentC.
I understand there is an option to check shouldComponentUpdate in childcomponent to prevent it get render. But, imagine I have over 100 of childcomponent, would it be frustrating to write over 100 times of shouldComponentUpdate method?
I need help here, please advice!
React doesn't provide any way to render children selectively. The component will either render or not. But I need to highlight a few points why this is not a problem when we use React in practice.
First of all, you don't need to manually implement shouldComponentUpdate for each component. If you don't want to rerender component if its props and state haven't changed, you can just extend from the PureComponent class instead of the Component class. Note that React.PureComponent's shouldComponentUpdate() only uses shallow comparison for state and props. But this shouldn't be a problem if you follow react best practices and avoid mutating the state.
Also, it's not practical to have more than 100 different components in one render method. React always encourages decomposing your UI into smaller components and using component composition. When we follow this approach, components will be nested inside each other in different levels instead of having a large number of components in one render method.
What I'm trying to explain is it's more practical and easy to manage when we compose our component in a nested fashion (2) rather than having lots of components inside a big container component (1).
In your example, if ChildComponentB and ChildComponentC are inside another component called ChildConatainerComponent then we only need to implement shouldComponentUpdate() for ChildConatainerComponent. Then it will automatically stop rendering any child element inside it.
render() {
return(
<ChildComponentA iconName={this.state.iconName}
toggleTick={() => this.handleToggleTick}/>
<ChildConatainerComponent/>
)
}
class ChildConatainerComponent extends PureComponent {
render() {
return (
<div>
<ChildComponentB/>
<ChildComponentC/>
</div>
);
}
}
Another very import concept to keep in mind is calling render function doesn't mean that React recreates all the DOM elements again. The render method only make changes to React virtual DOM which is an in-memory representation of DOM and it's faster than actual DOM. Then React compare versions of virtual DOM which are before the update and after the update and the actual DOM will be updated with only what has actually changed.
Another solution you could consider is moving iconName into ChildComponentA, considering this is the only component related to it.
I haven't been able to find a clear answer to this, hope this isn't repetitive.
I am using React + Redux for a simple chat app. The app is comprised of an InputBar, MessageList, and Container component. The Container (as you might imagine) wraps the other two components and is connected to the store. The state of my messages, as well as current message (the message the user is currently typing) is held in the Redux store. Simplified structure:
class ContainerComponent extends Component {
...
render() {
return (
<div id="message-container">
<MessageList
messages={this.props.messages}
/>
<InputBar
currentMessage={this.props.currentMessage}
updateMessage={this.props.updateMessage}
onSubmit={this.props.addMessage}
/>
</div>
);
}
}
The issue I'm having occurs when updating the current message. Updating the current message triggers an action that updates the store, which updates the props passing through container and back to the InputBar component.
This works, however a side effect is that my MessageList component is getting re-rendered every time this happens. MessageList does not receive the current message and doesn't have any reason to update. This is a big issue because once the MessageList becomes big, the app becomes noticeably slower every time current message updates.
I've tried setting and updating the current message state directly within the InputBar component (so completely ignoring the Redux architecture) and that "fixes" the problem, however I would like to stick with Redux design pattern if possible.
My questions are:
If a parent component is updated, does React always update all the direct children within that component?
What is the right approach here?
If a parent component is updated, does React always update all the direct children within that component?
No. React will only re-render a component if shouldComponentUpdate() returns true. By default, that method always returns true to avoid any subtle bugs for newcomers (and as William B pointed out, the DOM won't actually update unless something changed, lowering the impact).
To prevent your sub-component from re-rendering unnecessarily, you need to implement the shouldComponentUpdate method in such a way that it only returns true when the data has actually changed. If this.props.messages is always the same array, it could be as simple as this:
shouldComponentUpdate(nextProps) {
return (this.props.messages !== nextProps.messages);
}
You may also want to do some sort of deep comparison or comparison of the message IDs or something, it depends on your requirements.
EDIT: After a few years many people are using functional components. If that's the case for you then you'll want to check out React.memo. By default functional components will re-render every time just like the default behavior of class components. To modify that behavior you can use React.memo() and optionally provide an areEqual() function.
If a parent component is updated, does React always update all the direct children within that component?
-> Yes , by default if parent changes all its direct children are re-rendered but that re-render doesn't necessarily changes the actual DOM , thats how React works , only visible changes are updated to real DOM.
What is the right approach here?
-> To prevent even re-rendering of virtual DOM so to boost your performance further you can follow any of the following techniques:
Apply ShouldComponentUpdate Lifecycle method - This is applied only if your child component is class based , you need to check the current props value with the prev props value ,and if they are true simply return false.
Use Pure Component -> This is just a shorter version to above method , again works with class based components
Use React memo -> this is the best way to prevent Rerendering even if you have functional components ,you simply need to wrap your components export with React.memo like : export default React.memo(MessageList)
Hope that helps!
If parent component props have changed it will re-render all of its children which are made using React.Component statement.
Try making your <MessageList> component a React.PureComponent to evade this.
According to React docs: In the future React may treat shouldComponentUpdate() as a hint rather than a strict directive, and returning false may still result in a re-rendering of the component. check this link for more info
Hope this helps anyone who is looking for the right way to fix this.
If you're using map to render child components and using a unique key on them (something like uuid()), maybe switch back to using the i from the map as key. It might solve the re-rendering issue.
Not sure about this approach, but sometimes it fixes the issue