February 10, 2022
•
6 min read
Have you ever wondered why your component is re-rendering multiple times consecutively when you only expect it to re-render once? Perhaps you update some local state and somehow multiple renders occur as a result? Let's take this hooks-based example:
Under synchronous operations or with React event handlers, React will batch all setState
calls into a single render. However, React does not batch setState
calls when performing asynchronous operations. There are three solutions that I propose to clean up the unnecessary re-renders.
This solution couples dateA
and dateB
into a single object. This means that anytime you need to update dateA
or dateB
, you will be updating one object. The downside to this approach is that dateA and dateB will always be tightly coupled and you will always need to know the previous state to merge in with the new state when updating just one of the two dates.
This solution involves using React’s unstable_batchedUpdates
API. Although labelled unstable, I have not experienced any issues with this method. React does plan on implementing this behaviour as the default behaviour soon. This is probably the cleanest solution that decouples dateA
and dateB
.
useReducer
implements a redux state pattern into your local state. This allows you to perform multiple state updates in a single dispatch call. The redux state pattern is highly reliable but does require a lot of boilerplate code to write a reducer and your dispatch calls. If you’re using TypeScript, this adds a lot of bloat to a single component.
Another cause of excessive renders could come from your global state. Redux uses the unstable_batchedUpdates
API under the hood to batch their dispatch actions into a single call. This batch behaviour can be confirmed using the Redux Dev Tools.
Full demo of all 3 solutions are available on Code Sandbox.