Avoid excessive re-rendering in your React app by using `useObserver` and `useObserverListener` as an alternative to `useState`.
npm install react-hook-useobserveruseObserver and useObserverListener as an alternative to useState.
useState is frequently used hook. However, when you use the setState function, useState will immediately re-render the component.
jsx
import React, { useState } from 'react';
import {DataGrid} from './DataGrid'
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
);
}
function DisplayCount({count}){
return You clicked {count} times
}
`
The preceding scenario is an illustration of a common re-rendering issue in React application. We have an Example component with a state count,
and Example component render the DataGrid component. In general, the DataGrid component is huge and contains numerous rows.
If we don't conduct performance optimization, such as using React.memo, we will run into performance issue because React will re-render
the entire component when the function from setCount is called.
###### An alternative to the above method using the useObserver is as follows:
`jsx
import React, { useState } from 'react';
import {VeryComplexChart} from './VeryComplexChart'
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useObserver(0);
return (
);
}
function DisplayCount({count}){
return You clicked {useObserverValue(count)} times
}
`
By changing useObserver instead, we have simply ensured that the DataGrid will not be re-rendered when setCount is invoked.
When the setCount component is called, just the DisplayCount component is re-rendered.
$3
`jsx
const [count,setCount] = useObserver(0);
`
It declares a observable variable. Our variable is called count, but we could call it anything else, like banana.
This is a way to “preserve” some values between the function calls — useObserver is a new way to use the exact same
capabilities that useState provides in react hook.
The primary distinction between useObserver and useState is the useObserver function's return an array of mutable values
as well as the function used to setValue. The mutable value returned by useObserver is identical to the one returned by useRef.
As a result, we can utilize a property called "current" to access the current value of count.
`jsx
return {count.current}
`
$3
useObserver will not re-render the component to which it is attached.
So, if the component that utilizes useObserver hooks has extensive and complicated children,
re-rendering, and performance degradation can be avoided.
$3
To find out if an observer is updated when setValue is called, add an event listener to the observer itself.
So basically we can rewrite our example above to something like this.
`jsx
function Example() {
const [count, setCount] = useObserver(0);
return (
);
}
function DisplayCount({count}){
const [countValue,setCountValue] = useState(count.current);
useEffect(() => {
const removeListener = count.addListener((newCount,oldCount) => {
setCountValue(newCount);
});
return () => removeListener();
},[]);
return You clicked {countValue} times
}
`
The above code is an extended version of what we would do if we wanted to listen to the value of useObserver.
We can use useObserverListener hook instead using useEffect to add event listener to the observer.
`jsx
import {useObserverListener} from "./useObserverListener";
function DisplayCount({count}) {
const [countValue,setCountValue] = useState(count.current);
useObserverListener(count,(newCount) => {
setCountValue(newCount);
})
return You clicked {countValue} times
}
`
We can cut the code above in half by utilizing the useObserverValue hook to receive the value from the observer.
`jsx
import {useObserverValue} from "./useObserverValue";
function DisplayCount({count}) {
const countValue = useObserverValue(count);
return You clicked {countValue} times
}
``