npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-hook-useobserver

v1.0.0-alpha.19

Published

Avoid excessive re-rendering in your React app by using `useObserver` and `useObserverListener` as an alternative to `useState`.

Downloads

26

Readme

React Hook useObserver.

Avoid excessive re-rendering in your React app by using useObserver and useObserverListener as an alternative to useState.

Both useState is frequently used hook. However, when you use the setState function, useState will immediately re-render the component. Most of the time, we don't want to re-render the component right away, and we want to make sure that we're re-rendering the component that listens to the change of a specific attribute in the state only. As an alternative, we can utilize useObserver to fix this problem.

The following are examples of common uses of useState.
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 (
        <div>
            <DisplayCount count={count} />
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
            <DataGrid/>
        </div>
    );
}

function DisplayCount({count}){
    return <p>You clicked {count} times</p>
}

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:
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 (
        <div>
            <DisplayCount count={count} />
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
            <VeryComplexChart/>
        </div>
    );
}

function DisplayCount({count}){
    return <p>You clicked {useObserverValue(count)} times</p>
}

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.

What does calling useObserver do?

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.

return <div>{count.current}</div>

What are the benefits of using the useObserver?

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.

How to listen if an observer is updated

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.


function Example() {
    const [count, setCount] = useObserver(0);
    return (
        <div>
            <DisplayCount count={count} />
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
            <VeryComplexChart/>
        </div>
    );
}

function DisplayCount({count}){
    const [countValue,setCountValue] = useState(count.current);
    useEffect(() => {
        const removeListener = count.addListener((newCount,oldCount) => {
            setCountValue(newCount);
        });
        return () => removeListener();
    },[]);
    return <p>You clicked {countValue} times</p>
}

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.

import {useObserverListener} from "./useObserverListener";

function DisplayCount({count}) {
    const [countValue,setCountValue] = useState(count.current);
    useObserverListener(count,(newCount) => {
        setCountValue(newCount);
    })
    return <p>You clicked {countValue} times</p>
}

We can cut the code above in half by utilizing the useObserverValue hook to receive the value from the observer.

import {useObserverValue} from "./useObserverValue";

function DisplayCount({count}) {
    const countValue = useObserverValue(count);
    return <p>You clicked {countValue} times</p>
}

By using useObserver you can avoid excessive re-rendering of react.