Trying to understand, if simple react component without any props, that has been created as
const x = <div />
will be rendered in a more efficient way during tree comparison than memorized component?
const y = React.memo(<div />)
will be rendered in a more efficient way during tree comparison than memorized component?
There's no one good answer to that, because it depends on the case. If a component does not include any heavy logic, it's pointless to wrap it with memo because wrapping with memo uses memory and slows down your performance a bit.
In your particular example that you have shown in codesandbox, there's clearly no point to wrap your component with memo since there is not any complex logic inside.
And once again - in your particular case memo is pointless and will run slower than the component without memo (because the built-in shallow comparison of props has to take place). However, the differences in performance will be practically unnoticeable.
Related
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.
I am recently refactoring a web app using React Hooks. I encounter a problem regarding useCallback. Based on description of Kent: https://kentcdodds.com/blog/usememo-and-usecallback, useCallback is to pass in identical function reference to sub-components, to avoid re-render of sub-components, so that the performance is better. However, it's used together with React.memo. And as Kent said:
MOST OF THE TIME YOU SHOULD NOT BOTHER OPTIMIZING UNNECESSARY RERENDERS. React is VERY fast and there are so many things I can think of for you to do with your time that would be better than optimizing things like this. In fact, the need to optimize stuff with what I'm about to show you is so rare that I've literally never needed to do it ...
So, my question is: am I right to claim that we do not need to use useCallback usually? except when the callback is expensive to create, using useCallback avoids re-creating the callback for every render.
Say, for a onClick or onChange event handler, 2 lines or less, shall we just not use useCallback to wrap it?
I find the useCallback() is necessary when I don't want the function reference to change. For example, when I'm using React.memo on some child component that should not be re-rendered as a result of a reference change in one of its methods that comes through props.
Example:
In the example below Child1 will always re-render if Parent re-renders, because parentMethod1 will get a new reference on every render. And Child2 will not re-render, because the parentMethod2 will preserve its reference across renders (you can pass a dependency array to make it change and be re-created when new input values come).
Note: Assuming the Child components are being memoized with React.memo()
function Parent() {
const parentMethod1 = () => DO SOMETHING;
const parentMethod2 = useCallback(() => DO SOMETHING,[]);
return(
<React.Fragment>
<Child1
propA=parentMethod1
/>
<Child2
propA=parentMethod2
/>
</React.Fragment>
);
}
On the other hand, if the function is expensive to run, you can memoize its results using the useMemo hook. Then you will only run it when new values come, otherwise it will give you a memoized result from previous calculations using those same values.
https://reactjs.org/docs/hooks-reference.html#usecallback
useCallback
Pass an inline callback and an array of dependencies. useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).
useMemo
Pass a “create” function and an array of dependencies. useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.
I think you are right. From how it's designed, useCallback should be almost useless in React. It can not be used directly to prevent a child render.
What can save a child render is to wrap entire render using a useMemo.
const Title = () => {
...
const child = useMemo(() => {
return <Child a={"Hello World"} />
}, [])
return (
<>
{child}
<div onClick={onClick}>{count}</div>
</>
)
}
The above approach is a bit different than React.memo because it acts directly on the parent Title, instead of Child. But it's more or less answer your question why it's useless, except when you use it as the shortcut for useMemo.
Article explaining this, https://javascript.plainenglish.io/can-usememo-skip-a-child-render-94e61f5ad981
back to useCallback
Now let's go back to see if a callback wrapped with or without useCallback is useful.
<div onClick={onClick}>kk</div>
The only thing it might save is that when it's under reconciliation, onClick (with useCallback) points to the same function instance.
However I don't know if React actually does any optimization at that step. Because assigning a different callback to the attribute might take additional memory and time. But adding a new variable in general takes additional memory as well.
So this type of optimization is more like a coding optimization, more or less subjective. Not objective enough to be applied in a solid case.
Of course, if you want to fix a function instance for any third party function, ex. debounce. That might be a good use, but still smell fishy, because useMemo seems much more versatile to cover this case as well.
All in all, I'm only pointing out, useCallback isn't doing what's the public believe it can do, such as to bailout child component.
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
I've recently decided to refresh on react's documentation and came across https://reactjs.org/docs/react-api.html#reactmemo (React.memo).
At first glance it looked like a good candidate for pretty much all of my function components. So I did just that and applied memo on all of them.
I'm not sure if I am able to notice dramatic performance boost, but it for sure didn't make anything slower.
Hence the question: should I apply memo to all my fucntion components by default, just in case so I can catch edge cases of re-rendering a lot of elements? Are there any drawbacks to this / something else i need to be aware of?
No, you shouldn't memoize all your function components by default. You should decide when to do this on a case-by-case basis.
1. It's only for "pure" function components (as in, without side effects)
From the documentation:
If your function component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result.
Imagine that you add some side effect to your function component, for example, reading the current time from Date.now(). The component will work as expected the first time it's called with certain props, but the next time it's called with those same props, the old time will be used. This can lead to confusing bugs.
2. Not all pure function components will benefit from memoization
For example, if it's unlikely a component will ever be called with the same props, then memoizing the result will likely lead to worse performance. After all, memoization is just storing the result of a function call to an object, where the key is derived from the input to the function and the value is the result of the function call. Why store this if you'll never use it?
3. Memoization is more useful for functions that are computation intensive
If your function component doesn't take many CPU cycles to render, then any performance optimization is likely going to be negligible. But it's now possible to later add side effects to that component, forget that it's being memoized, and waste time fixing the resulting bugs.
Again, from the docs:
This method only exists as a performance optimization. Do not rely on it to “prevent” a render, as this can lead to bugs.
For shorter explanation:
If React.memo() everything makes React more efficient and optimized, it should be considered as a default behavior, not only an option (like pure function).
Basically, React.memo() prevents redundant rerenders by comparing the component's previous and current props.
<Parent>
<Child />
</Parent>
Normally, when the Parent rerenders, the Child rerender as well by default.
With React.memo(), if the props passed into Child are not changed when Parent rerender, Child does not rerender.
The question here is: why does React know props passed to Child was not changed in the current rerender?
The answer is: React itself has to do a comparison, and it is the cost of React.memo()
If the time to comparison > the time to just rerender the whole Child component, it even slows down your app.
Right now I'm using reselect to create my selectors to extract data from the store and pass it to the props via connect.
For simplicity, the result of my selectors is always a JS object (calling toJS() at the end of the selector), something like this:
const selector = state => state.get('data').toJS();
Now I'm trying to improve some performance and I realized that shouldComponentUpdate shallow comparison loses the advantages of immutability because of the way I'm returning from my selectors.
On the other hand, using .get('prop') inside my html seems extremely annoying:
<div>{this.props.data.get('prop')}</div>
Especially if I have a case of passing a simple JS object to a child component which is mutable, like this:
<ChildComponent totalItems={10} />
And then there is no consistency when accessing the props (some are mutable and some are immutable).
I thought of creating an helper unwrap function, something like this:
const unwrap = obj => obj && obj.toJS ? obj.toJS() : obj;
But I don't really like this solution.. I don't really like any of those approaches.
What do you use for both clean code & performance?
To pass props to component collect all data under a key as immutable.
<MyComponent propsKey={Immutable.fromJS({someData: {key: "value"}})} />
To use benefits of Immutable you should avoid from use toJS(). It is very costly and you cannot use useful Immutable functions with that. Until you reach "value", you should use Immutable.get(). It is annoying at first but, you can see how it is useful and easy to use, in time. (To get inner keys using getIn() can be less annoying than chain get functions). In this way your code can work more efficient and you do not need to use unwrap function, in your component you guarantee your data under this.props.propsKey always immutable.
You should wrap your presentational components in a simple higher-order component that calls toJS() on any Immutable.js object props passed to it.
This will give you the best balance of keeping the performance benefits of Immutable.js whilst keeping your container components from re-rendering too much, as well as keeping your presentational components dependency-free and therefore easily reusable and testable.
The Redux docs have a good selection of best practises for using Immutable.js, in particular, when not to use .toJS(), why your presentational components should be kept pure and how a "toJS" higher-order component might be defined and used.
Coming back to my question a year and a half later with my own answer:
Always pass the immutable object if possible. If it's not immutable, just pass it as it is.
I decided that performance is much more important than how pretty the code is.
If a value is either immutable or mutable I pass it as it is and never call toJS if I don't have to. I also won't wrap mutable values with fromJS if they're not stored in the redux store.
I just need to be aware inside the child component that some props are immutable and some are not - and it's actually pretty simple because almost always a complex object will be immutable.