Comment optimiser les re-renders dans React pour améliorer les performances de votre application. Cet article explique les causes des re-renders, leurs impacts, et présente des stratégies efficaces comme React.memo, le découpage du code et la gestion d'état pour réduire les re-renders inutiles
React is a library used to simply build applications using components, these components are then re-rendered based on state and props change. However, improper usage of state and props change can lead to unnecessary re-renders, which can impact the application's performance and therefore the user experience. The purpose of this article is to explain how re-renders work in React and to present some practical strategies to optimize these re-renders.
React re-renders components when state, props, or context changes, but unnecessary re-renders can harm performance, leading to issues like laggy UIs and increased memory usage. Detecting re-renders using tools like React DevTools
or the Why Did You Render
library is crucial for optimizing your app. Key strategies to reduce unnecessary re-renders include:
Optimizing re-renders ensures a smoother UI, but the balance between the performance of the application and the maintainability of the code should always be considered.
There are several reasons that can lead to a component’s re-render:
Too many re-renders can increase the amount of computation React has to perform, which leads to performance issues. It can be especially noticeable in large apps or when the re-rendered components trigger expensive operations (e.g., API calls, complex calculations).
In an application, this can lead to:
Detecting re-renders is key in order to optimize your application’s performances. Here are some methods that can help detect and understand re-renders:
React.memo
allows you to memoize a component which can help preventing unecessary re-renders. If a component is wrapped in React.memo
, it will only be re-rendered if one of its props changes.
This solution is suitable for functional components with heavy computation or when you know the props won't change frequently.
However, inappropriate usages of it might cause performance issues as React needs to compare the props everytime the parent component is re-rendered. It can be the case if for example a memoized component with props is wrapped in a parent component which re-render at any input of the user.
In this example, every time the user sends a message, the components Header , MessageList and MessageInput are re-rendered.
If we decide to memoize the header with React.memo
, the header is then rendered on the page load and will never be re-rendered as none of its props change.
Splitting code not only keeps it readable and maintainable, but also helps optimize re-renders. In fact, splitting a component into sub-components allows state changes to be placed at a lower level, allowing only the components that needs to be re-rendered to be re-rendered.
In this example, every time the user enters a character in the text input the state textInput
changes leading to the re-render of all the components inside Component
If we decide to use a zustand store to store the messages and subscribe to the list of messages in the component MessageList. Then every time the user sends a message, only the component MessageList will be re-rendered.
Global state management using stores (like Zustand) can minimize unnecessary re-renders, especially when managing global state across multiple components. With the stores, it allows your components to subscribe a specific slice of state, reducing unnecessary re-renders in component that don’t use the full store.
In this example, every time the user clicks on Send
the list of messages
is updated, leading to the re-render of the Header
, the MessageList
and the MessageInput
.
If we decide to use a zustand store to store the messages and subscribe to a list of messages
in the component MessageList
. Then every time the user sends a message, only the component MessageList
will be re-rendered.
Optimized re-renders are essential in order to guarantee a seamless and effective user experience, particularly when the component tree's complexity increases. This can be achieved by using strategies like React.memo, code splitting and the stores which will help you minimize unnecessary renders.
Developers should monitor re-renders closely, however the balance between the performance of the application and the maintainability of the code should always be considered.