Here we’ll show you an intricate guide on how to correctly apply useSelector to efficiently render components, how to set up the custom compare function to avoid rendering and how to memoize components, helping performance by reducing the number of times the logic inside the selector is triggered
iOS Developer at Nuvolar
This article aims to describe the best options the Mobile team at Nuvolar considers when using functional components that connect to the Redux Store thanks to the useSelector hook.
After previous discussions, the team decided to set a goal: to write this “Best Practices” article to make sure that, from now on, we all use the same, correct and consistent, approach, which we are explaining in detail here.
1. useSelector: The hook which allows you to extract data from the Redux Store.
The selector is approximately equivalent to mapStateToProps and will be called when the store state changes.
Please note that useSelector will do a reference comparison (===) of the previous selector result.
If the result is different the component will be re-rendered. For primitive values, this will have no major impact but please take this into consideration when working with objects (including arrays).
useSelector is called every time an action is dispatched to the store.
1a. Destructuring: Best way to avoid unnecessary rendering
As mentioned previously, the useSelector will use strict reference equality to decide whether a render has to be triggered or not. Imagine the following scenario:
If the user’s state object reference changes (even maintaining the values for name and photo keys) the component will re-render (it is comparing 2 different objects references).
In order to avoid this unnecessary render please consider the following approach:
This will only render if the values for the keys name and photo change. useSelector will be comparing primitives in this case, so only if the string value is different the render will be triggered.
There is no inconvenience in creating a new useSelector for each value. This is what the documentation states:
You may call useSelector() multiple times within a single function component. Each call to useSelector() creates an individual subscription to the Redux Store. Because of the React update batching behavior used in React Redux v7, a dispatched action that causes multiple useSelector()s in the same component to return new values should only result in a single re-render.
1b. Comparing objects
In case you have the need to compare objects and you can not use values instead, there are still 2 options one can use.
Remember, the main goal is to avoid re-rendering when it is not strictly necessary (because a value used for rendering purposes changed).
- Custom compare function:
You can specify a function that will be used to compare the result of the selector. Feel free to implement your own or to use the already existing shallowEqual.
Please bear in mind that this may hit the performance since shallowEqual may be heavy in terms of processing (depending on the object shape).
Use reselect or a similar library that returns multiple values in one object, but only returns a new object when one of the values has changed. On top of that, this approach helps performance by reducing the number of times the logic inside the selector is triggered.
2. React.memo: helping memoize with parent components
Even when you are properly preventing your component to re-render based on the proper usage of useSelector there are still situations in which it can get rendered unnecessarily.
This may happen when the parent component re-renders (parent state changes).
In order to fix this issue React.memo helps memoize the component and return the cached version if the props have not changed.
Imagine the following scenario:
When “increment()” is triggered, the state changes and this will re-render the component and all its children, UserComponent included.
There is no need for this since the component will be re-rendered with the exact same layout and content.
Avoid this by using the React.memo hoc.
Afterwards the component returned, when the parent is re-rendered, will be the memoised version.
3. Additional Resources
JUNE 1, 2022· BY NUVOLAR WORKS
Our way to a fancy QA automation reporting
Discover a faster and more efficient way to create automated QA reports: We’ll guide you through the best QA reporting tools and the most optimal processes so that you can integrate them with Jira and TestRail and save you an incredible amount of time!
JANUARY 24, 2022· BY NUVOLAR WORKS
Salesforce best practices: 6 points every administrator should keep in mind
The proper functioning of Salesforce depends, in part, on its administrator. In this article, we review the most important points that cannot be overlooked by the technician responsible for CRM in a company.
- 4 MIN
MARCH 8, 2021· BY NUVOLAR WORKS
Strategies for successfully migrate to the cloud
Strategies for successfully migrate to the cloud Both consolidated companies and those in the process of growth should consider the option of managing their processes through “cloud” environments. The cloud model has been a revolution when it comes to automating and optimizing tasks, as well as facilitating access to company data and systems. Thus, the transition […]
- IT CONSULTING
- 4 MIN