When the state changes in a React component, the entire component re-renders, causing all functions and data to be recalculated. This can slow down our application, especially if there are expensive calculations involved.
When state change our entire component re-render, so all the functions and data will be re-render and slow down our app
import { useState } from "react"
const UseMemo = () => {
const [number, setnumber] = useState(0)
const [dark, setdark] = useState(false)
const dblNumber = slowFunc(number)
const themestyle = {
background: dark ? 'black' : 'white',
color: dark ? 'white' : 'black'
}
return ( <>
<input type="number" value={number}
onChange={(e) => setnumber(parseInt(e.target.value))} />
<button onClick={() => setdark(prevVal => !prevVal)}>Change Theme</button>
<div style={themestyle}>{dblNumber}</div>
</> )
}
const slowFunc = (n) => {
console.log('Function Start')
for (let i = 0; i <= 1000000000; i++) { null }
console.log('Function End')
return n * 2
}
export default UseMemo
We create input that value is number, theme changing button and display data div. Here we see when we change the value of input function call and data load more but when we change theme that time also data load and slow down our component.
So here we see only data load when numbers change, not that time when themes change.
We useMemo to memorise changes.
First time we change the number that time value from 0 to 1 calculate and ( value change so) function run, and return value stored in memory, But when we change theme that time value is 1 and output is stored in memory so useMemo hook easily gives value without run function.
So when we change the theme that time slowFunc value store in memory useMemo hook.
const dblNumber = useMemo(() => {
return slowFunc(number)
}, [number])
Now when we change the number that time runs the function, otherwise it gives value from memory.
We see in Javascript value vs references, In case of Object and Array same value two object or array are different.
const val1 = { bg: 'grey', val: 0 } and const val2 = { bg: 'grey', val: 0 }
These two objects are different, their values are the same but their references are different.
Now we have this problem in react also. So we solve using the useEffect hook. When the themestyle changes that time render otherwise no, but component re-render and objects and array are also re-render.
useEffect(() => {
console.log('Theme Changes')
}, [themestyle])
We have a themestyle object whose value is the same for every time in the component but when we change state value themestyle also re-create, when data is big that reduces our app quality, So we use memo for that type of object.
const themestyle = useMemo(() => { return {
background: dark ? 'black' : 'white',
color: dark ? 'white' : 'black'
} }, [dark])
useEffect(() => {
console.log('Theme Changes')
}, [themestyle])
import { useState, useMemo } from "react";
const UseMemo = () => {
const [number, setNumber] = useState(0);
const [dark, setDark] = useState(false);
const dblNumber = useMemo(() => slowFunc(number), [number]);
const themeStyle = useMemo(() => ({
background: dark ? 'black' : 'white',
color: dark ? 'white' : 'black'
}), [dark]);
return (
<>
<input
type="number"
value={number}
onChange={(e) => setNumber(parseInt(e.target.value))}
/>
<button onClick={() => setDark(prevDark => !prevDark)}>Change Theme</button>
<div style={themeStyle}>{dblNumber}</div>
</>
);
};
const slowFunc = (n) => {
console.log('Function Start');
for (let i = 0; i <= 1000000000; i++) { null }
console.log('Function End');
return n * 2;
};
export default UseMemo;
In the above component, changing the input value triggers the slowFunc
function, which performs a time-consuming calculation. Additionally, changing the theme also causes the function to run, impacting the component's performance.
To optimize performance and prevent unnecessary recalculations, we can use the useMemo
hook. This hook memoizes the result of a function, returning the cached result when the dependencies remain unchanged.
useMemo
is useful for optimizing expensive computations or preventing unnecessary re-renders in React components.
useMemo
We use useMemo
to memoize the result of the slowFunc
function, ensuring that it only runs when the number
state changes.
const dblNumber = useMemo(() => slowFunc(number), [number]);
Additionally, we use useMemo
to memoize the theme style object, preventing it from being recreated on every render when the dark
state changes.
const themeStyle = useMemo(() => ({
background: dark ? 'black' : 'white',
color: dark ? 'white' : 'black'
}), [dark]);
useEffect
In some cases, objects or arrays may be recreated unnecessarily on every render, even when their values remain the same. We can further optimize performance by using useMemo
in conjunction with useEffect
to memoize such objects.
useEffect(() => {
console.log('Theme Changes');
}, [themeStyle]);
By memoizing the themeStyle
object, we ensure that the useEffect
hook only runs when the theme changes, rather than on every render.
Optimizing performance in React is essential for maintaining a smooth user experience. Use useMemo
and useEffect
judiciously to prevent unnecessary recalculations and re-renders.
useMemo
Objective: Optimize performance by memoizing expensive computations or objects using the useMemo
hook.
Memoize Expensive Computation:
Create a new file ExpensiveComputation.jsx
and define a component that performs a time-consuming calculation.
// ExpensiveComputation.jsx
import React, { useState, useMemo } from 'react';
const ExpensiveComputation = () => {
const [number, setNumber] = useState(0);
const [result, setResult] = useState(0);
const calculateResult = (n) => {
// Simulate a time-consuming calculation
for (let i = 0; i < 1000000000; i++) { }
return n * 2;
};
const memoizedResult = useMemo(() => calculateResult(number), [number]);
const handleInputChange = (e) => {
setNumber(parseInt(e.target.value));
};
const handleButtonClick = () => {
setResult(memoizedResult);
};
return (
<div>
<input
type="number"
value={number}
onChange={handleInputChange}
/>
<button onClick={handleButtonClick}>Calculate Result</button>
<p>Result: {result}</p>
</div>
);
};
export default ExpensiveComputation;
Test Performance:
Import and use the ExpensiveComputation
component in your App
component to test the performance improvement achieved by memoizing the calculation using useMemo
.
// App.jsx
import React from 'react';
import ExpensiveComputation from './ExpensiveComputation';
const App = () => {
return (
<div>
<h1>Optimizing Performance with useMemo</h1>
<ExpensiveComputation />
</div>
);
};
export default App;
Measure Performance:
Use browser developer tools or performance monitoring tools to measure the difference in rendering time between the memoized and non-memoized versions of the calculation.
Note: Compare the rendering time before and after using useMemo to observe the performance improvement.
This task will help you practice using the useMemo
hook to optimize performance in React components by memoizing expensive computations.