Open panzerdp opened 3 years ago
Comment written by Robert Cooper on 07/20/2019 06:59:10
Great read! Where did the following quote come from?
Performance-related changes applied incorrectly can even harm performance. Use React.memo() wisely.
I'm curious to read more about performance implications of over using memoization in React applications.
Comment written by Dmitri Pavlutin on 07/20/2019 08:13:08
Thanks @disqus_t8zxzdWNo5:disqus!
The quote you're mentioning is mine. It's a key takeaway.
I will think about writing a post that measures the performance gains of memoization.
Comment written by Young Moon on 07/25/2019 01:02:09
@disqus_t8zxzdWNo5:disqus
Maybe in case of using memoization for regularly update with new props can lead to useless comparison costs.
Comment written by Robert Cooper on 07/25/2019 01:03:49
Yes, perhaps. Good point.
Comment written by Michael on 07/26/2019 02:14:41
Of course, you cannot use React.memo() on non-pure components, e.g. components that have state
I don't think this is true. Memoised components which have internal state (via `useState`) will still re-render if that state changes, even if their props have not.
Comment written by Michael on 07/26/2019 02:50:44
With the default comparator, the comparison cost should be negligible, even with a large number of props.
Comment written by Dmitri Pavlutin on 07/26/2019 07:03:02
I think it's not correct to ignore memoization equality check costs. That's a code smell and would lead to inappropriate use of memoization.
For a typical use case of your component, you should use profiling to determine whether the component performs faster with memoization or without it. The outcome depends on how often your component re-renders with the same props.
Comment written by Dmitri Pavlutin on 07/26/2019 07:27:23
You're right, it's not a mistake to use state hook with memoization. Post updated.
Comment written by Porfírio Ribeiro on 07/26/2019 08:15:12
I use that with components that useContext and do lots of stuff when context change, but i don't need them to update when parent change because of some unrelated state.
Works pretty good
Comment written by andrepcg on 08/03/2019 09:53:03
4. Why not just do the following without having to use `useCallback`?
`onLogout={cookies.clear}`
Comment written by Dmitri Pavlutin on 08/03/2019 15:44:51
Because you need to call cookies.clear() without arguments.
Comment written by andrepcg on 08/03/2019 16:25:43
Since you don't go into details about the `cookies.clear()` function and the way it is called, I assumed calling it with or without arguments would be the same. But with that new constraint (must be called without arguments) then you are right
Comment written by disqus_dmflxzVdEa on 08/18/2019 09:21:50
In the useCallback snippet you provide an empty dependency array, while you are referencing the cookies prop in the function. So if the cookies prop changes at any time, the function returned by useCallback will still have a reference to the cookies received on mount. You should add cookies to the dependency array like this: const onLogout = useCallback(() => { cookies.clear() }, [cookies]);
. This way useCallback will compare the previous dependencies to the current ones, and if any of them have changed, it will return a new function which closes over the current dependencies.
Comment written by Dmitri Pavlutin on 08/19/2019 08:34:49
Thanks for the detailed description!
I consider `cookies` prop a singleton (or a namespace) that does not change during runtime. That was my initial though regarding empty dependency of useCallback().
But now I see the need to clear the reference when `cookies` changes. This might happen during testing since I would like to use multiple mock instances of `cookies`: to check whether cookies are cleared on logout.
Post updated.
Comment written by Joshua Barker on 10/04/2019 14:16:51
In your examples, you only every use your memoized component as a single instance... I'm confused and have not been able to find an answer to this question... is the MemoizedComponent returned by React.memo(fn) a singleton like reselect's createSelector function, or can it be used to create multiple, independent memoized component instances?
Example: Is this valid?
// MovieList component
render() {
const { movies } = this.props;
return (
<div>
{
movies.map((movieData) => {
return (<memoizedmovie {...moviedata}=""/>);
});
}
</div>
);
}
or can MemoizedMovie only ever be used as a single instance?
* this code editor sucks...
Comment written by Dmitri Pavlutin on 10/04/2019 14:49:48
Think of the memoized component exactly as the original one, only that internally it will not re-render if the props are the same.
You can use the memoized component anyhow you like, including the creation of multiple instances.
Comment written by Namrata Saun on 02/19/2020 08:35:16
You can do that. Functional components are stateless (this is practically not true), usually.
The 6th point clearly states that you can use hooks and they will work normally. It's like extending PureComponent just with optional conditions
Comment written by Cihat Imamoglu on 06/03/2020 20:55:23
This was a very well-written article, thanks a lot!
Comment written by Dennis Felyx on 10/02/2020 17:18:12
Hello,
I'm confused by that statement: "If the component doesn’t re-render often with the same props, most likely you don’t need React.memo()."
Example scenario: show a list of names and allow to change them.
List consists of multiple list items (each is a separate component).
Each list item is wrapped in React.memo and accepts a name and a callback (which in parent is wrapped in useCallback).
Each time I edit list item #3, all other are re-rendered. I think it's ok to use React.memo with list item component.
What do you think?
Comment written by Dmitri Pavlutin on 10/14/2020 08:02:25
Hey Dennis,
You need to profile the performance of the component with and without React.memo(), then decide by yourself is the performance gains worth it.
Thanks a lot for your brilliant post, now I just understand more about react re-rendering and how to optimize my pure functional component with React.memo.
Thanks a lot for your brilliant post, now I just understand more about react re-rendering and how to optimize my pure functional component with React.memo.
You're welcome @peterczg.
Thanks, great article.
Great explanation, Thanks for sharing your knows.
Great explanation, Thanks for sharing your knows.
Thanks @ecatugy!
I wonder if all stateless ui components built with using styled components should be exported wrapped in react memo
I wonder if all stateless ui components built with using styled components should be exported wrapped in react memo
Profile and measure the performance gains (if any), then decide to use memo or not.
React always re-renders the component if the state changes, even if the component is wrapped in React.memo()
Even if the props has not changed?
React always re-renders the component if the state changes, even if the component is wrapped in React.memo()
Even if the props has not changed?
Yep.
Thanks .. It's awesome
Thanks .. It's awesome
Thank you for the article. I do have a question.
Does the section "3.1 Useless props comparison" mean that even with the props comparison, it wouldn't be able to make a decision if it need to render or not? so we just do the render without shallow check of the component ?
Sorry i don't understand what that second tries to deliver. I do see in the source code, props are not even shallow compared, it's just compared with a ===
.
Thank you for the article. I do have a question.
Does the section "3.1 Useless props comparison" mean that even with the props comparison, it wouldn't be able to make a decision if it need to render or not? so we just do the render without shallow check of the component ?
Sorry i don't understand what that second tries to deliver. I do see in the source code, props are not even shallow compared, it's just compared with a ===.
I believe the general point is if you're repeatedly passing differing props frequently enough, then the component is going to rerender regardless, so there's no point in memoizing.
I believe the general point is if you're repeatedly passing differing props frequently enough, then the component is going to rerender regardless, so there's no point in memoizing.
thanks Dave, I thought all props are not compared, maybe only the reconciliation does in the end? So why do we care if the props are different, because React seems to take a different object of props in every render anyway?
I did a simple test
App
Branch1
Count(count)
Nothing1
Nothing1-1
Nothing2
Branch2
The count
state is installed inside Branch1
. It seems to me no matter what Nothing1-1
is rendered every time when this state changes.
Of course this is when no memo
is used. But i'm still very surprised, because all the discussion on the internet about prop checking to me is just none sense now.
I believe the general point is if you're repeatedly passing differing props frequently enough, then the component is going to rerender regardless, so there's no point in memoizing.
That's the idea.
Thanks for sharing your knows!!!!!!!
Thanks for sharing your knows!!!!!!!
You're welcome @junho0956!
Comment written by Robert Cooper on 07/20/2019 06:59:10
Great read! Where did the following quote come from?
Performance-related changes applied incorrectly can even harm performance. Use React.memo() wisely.
I'm curious to read more about performance implications of over using memoization in React applications.
@panzerdp Where did that quote come from? It doesn't look like there was ever a response and I'd like to read the article this came from too!
I think there is an escape for functions causes re-renders even provided username is same.
From
function Logout({ username, onLogout }) {
return (
<div onClick={onLogout}>
Logout {username}
</div>
);
}
const MemoizedLogout = React.memo(Logout);
To: Here as you can see, I've provided a comparison function and it only compares username. I think this is good idea to memoize. IF you don't pass REALLY different onLogout fn as a prop in parent cmp any time, so you don't need to compare it..
function Logout({ username, onLogout }) {
return (
<div onClick={onLogout}>
Logout {username}
</div>
);
}
const MemoizedLogout = React.memo(Logout, (prev, next) => prev.username === next.username);
What do you think?
Components using hooks can be freely wrapped in React.memo() to achieve memoization.
React always re-renders the component if the state changes, even if the component is wrapped in React.memo().
Does this mean that If we are wrapping a functional component with React.memo then there is no performance benefits. Have I understood something wrong? Please clear my doubt...
Hi, I'm trying to understand memo api but I still don't get it. I write a question in stackoverflow based on your post, can you give me a hand? Ty. https://stackoverflow.com/questions/72775948/how-react-memo-works-with-usecallback
Can you make a blog on how exactly react works?
@decpk
Does this mean that If we are wrapping a functional component with React.memo then there is no performance benefits. Have I understood something wrong? Please clear my doubt...
No. React will always rerender if state changes. The thing is that it will then also try to rerender all of the children of that component as well. React.memo allows us to make sure that BigExpensiveChild
isn't rerendered if it "doesn't need to" (i.e. if the props we're passing to it are the same as they were last time it rendered).
However if BigExpensiveChild
has some local state with useState
and something triggers a change in that state, BigExpensiveChild
will rerender. Which is what we want ofc
@kenanyildiz
Sure that works but that's exactly what the purpose of useCallback
is meant to solve. In the parent component we can wrap the onLogout
with useCallback
and we won't have to worry about it triggering unnecessary rerenders
The reason why this is preferred is because it's more maintainable. What if in the future you also add a disabled
prop to Logout
. Then you would have to update your custom memoization function to check for differences in that as well.
Or what if in the future you wanted to expand the logic of onLogout
to depend on some parent-level state. Then you wouldn't be able to rerender the Logout
component when your function does actually change
Thanks for this - a really useful guide on how to use React memoization correctly 🙂
Written on 07/10/2019 12:24:16
URL: https://dmitripavlutin.com/use-react-memo-wisely/