This content originally appeared on Bits and Pieces - Medium and was authored by Chameera Dulanga
How to Avoid Unnecessary Re-rendering in React
React components have evolved a long way from their inception. Still, many developers find it hard to fix unnecessary re-renderings. However, there are many approaches out there to avoid this issue.
In this article, I will discuss 5 methods to avoid unnecessary re-renderings in React components.
1. Memoization using useMemo() and UseCallback() Hooks
Memoization enables your code to re-render components only if there’s a change in the props. With this technique, developers can avoid unnecessary renderings and reduce the computational load in applications.
React provides two Hooks to implement memoization:
- useMemo()
- UseCallback()
These Hooks reduce re-renderings by caching and returning the same result if the inputs are the same without any computations. When the inputs change, the cache gets invalidated and the new component state gets rendered.
useMemo()
To understand how we can use the useMemo() Hook, let's consider an example of multiplying 2 numbers.
const multiply = (x,y) => {
return x*y
}
The above function will compute the result and re-render the component each time it is called, regardless of the inputs. But, if we use the useMemo() Hook, we can avoid component re-rendering if the inputs are the same and save the result in the cache.
const cachedValue = useMemo(() => multiply(x, y), [x, y])
Now, the computed result is stored in the cachedValue variable and useMemo() Hook will return it each time unless the inputs are changed.
UseCallback()
UseCallback() is another React Hook to implement memoization. But, unlike useMemo(), it does not cache the result. Instead, it memoizes the callback function provided to it.
For example, consider a component with a clickable item list.
import { useCallback } from 'react';
export function MyParent({ term }) {
const onClick = useCallback(event => {
console.log('Clicked Item : ', event.currentTarget);
}, [item]);
return (
<Listitem={item} onClick={onClick}
/>
);
}
In the above example, useCallBack() memoizes the onClick callback. So, it will not re-render the component if the user clicks the same item again and again.
2. API Call Optimization with React Query
It’s common to use the useEffect() Hook for asynchronous data fetching operations in React applications. However, useEffect() runs and fetches data on each render, and in most situations, it keeps loading the same data.
As a solution, we can use the React Query library to cache the response data. When we make an API call, React Query will first return the data from the cache before continuing with the request. Then, it will retrieve the data from the server, and if there is no new data available, it will prevent the component from re-rendering.
import React from 'react'
import {useQuery} from 'react-query'
import axios from 'axios'
async function fetchArticles(){
const {data} = await axios.get(URL)
return data
}
function Articles(){
const {data, error, isError, isLoading } = useQuery('articles', fetchArticles)
if(isLoading){
return <div>Loading...</div>
}
if(isError){
return <div>Error! {error.message}</div>
}
return(
<div>
...
</div>
)
}
export default Articles
React Query library has more than 600K weekly NPM downloads and 1.3K+ GitHub Stars.
3. Creating Memoized Selectors with Reselect
Reselect is a third-party React library for creating memorized selectors. It is commonly used with Redux stores and has amazing features to reduce unnecessary re-renderings.
- Reselect selectors are capable of computing derived data.
- Reselect selectors do not recompute unless their arguments are changed.
- They can be used as inputs to other selectors.
Reselect provides an API named createSelector, and it can generate memoized sector functions. For better understanding, let's consider the example given below.
import { createSelector } from 'reselect'
...
const selectValue = createSelector(
state => state.values.value1,
state => state.values.value2,
(value1, value2) => value1 + value2
)
...
Here, the createSelector takes 2 selectors as the input and returns the memoized version. Selectors will not be computed again with this memoized version until the values are changed.
Reselect library has more than 2 Million weekly NPM downloads and 18.4K+ GitHub stars.
4. Replace useState() with useRef()
useState() Hook is widely used in React applications to re-render the components on state changes. However, there are scenarios where we need to track state changes without re-rendering the components.
But, if we use the useRef() Hook, we can track the state changes without causing component re-renderings.
function App() {
const [toggle, setToggle] = React.useState(false)
const counter = React.useRef(0)
console.log(counter.current++)
return (
<button onClick={() => setToggle(toggle => !toggle)} >
Click
</button>
)
}
ReactDOM.render(<React.StrictMode><App /></React.StrictMode>, document.getElementById('mydiv'))
The above example has a toggle that re-renders the component each time the value changes. But the counter persists its value since it is a mutable ref. Since we are using useRef(), it will only cause a single render. However, if we use useState(), it will cause 2 renders for each toggle.
5. Using React Fragments
If you have worked with React before, you will know that React requires wrapping the components with a single parent element. Though it’s not directly about re-rendering, have you known that it affects the overall component rendering time?
As a solution, you can use React Fragments to wrap the components, and it will reduce the load on the DOM, resulting in faster rendering times and decreased memory usage.
const App= () => {
return (
<React.Fragment><p>Hello<p/><p>World<p/></React.Fragment>
);
};
Conclusion
In this article, I have discussed 5 different methods to prevent unnecessary re-rendering in React components. Most of these solutions capitalize caching, and you can use inbuilt React Hooks or 3rd party libraries to implement them.
In addition, these methods will improve your application performance to prevent unnecessary re-rendering while reducing the memory overhead.
I hope you have found this useful. Thank you for reading!
Build modular, reusable React components with Bit
Monorepos are a great way to speed up and scale app development, with independent deployments, decoupled codebases, and autonomous teams.
Bit offers a great developer experience for building component-driven monorepos. Build components, collaborate, and compose applications that scale. Our GitHub has over 14.5k stars!
Learn more
- Building a React Component Library — The Right Way
- 7 Tools for Faster Frontend Development in 2022
- Microservices are Dead — Long Live Miniservices
5 Ways to Avoid React Component Re-Renderings was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Bits and Pieces - Medium and was authored by Chameera Dulanga
Chameera Dulanga | Sciencx (2022-01-12T08:39:26+00:00) 5 Ways to Avoid React Component Re-Renderings. Retrieved from https://www.scien.cx/2022/01/12/5-ways-to-avoid-react-component-re-renderings/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.