React useProgState

A progressive React hook that expands useState features

Features

  • It prevents re-render if the value is not changed
  • Deep object comparison support, if nested object not changed, it will not re-render
  • You can set and access the state inside the event listener callback function
  • Optional parameter to prevent re-rendering manually

Installation

yarn add react-use-prog-state

or

npm i --save react-use-prog-state

Usage

import { useEffect, useRef } from 'react'
import { useProgState } from 'react-use-prog-state'

const MyApp = () => {
    const [counter, setCounter] = useProgState({ count: 0 })
    const renderCount = useRef(0)

    useEffect(() => {
        setCounter({ count: 0 })
        // result: render count doesn't change

        console.log(counter)
        // result: { count: 0 }
    }, []}

    return (
        <>
            <p>{renderCount++}</p>
            <p>{counter}</p>
        </>
    )
}

export default MyApp

If your value changes and you want to prevent re-rendering manually, you can pass the optional parameter to prevent re-rendering manually.

import { useEffect, useRef } from 'react'
import { useProgState } from 'react-use-prog-state'

const MyApp = () => {
    const [counter, setCounter] = useProgState(0)
    const renderCount = useRef(0)

    useEffect(() => {
        setCounter(1, true) // second param is preventRender?: boolean
        // result: render count doesn't change
    }, []}

    return (
        <>
            <p>{renderCount++}</p>
            <p>{counter}</p>
        </>
    )
}

export default MyApp

If you want to access the state inside the event listener callback function, you can use the stateGetter method.

import { useEffect, useRef } from 'react'
import { useProgState } from 'react-use-prog-state'

const MyApp = () => {
    const [counter, setCounter, counterGetter] = useProgState(0)
    const renderCount = useRef(0)

    const onKeyDown = (e) => {
        setCounter(counter + 1)

        const counterState = counterGetter()

        console.log(counterState) 
        // the result is 1 and the component is re-rendered 
    }

    useEffect(() => {
        document.addEventListener('keydown', onKeyDown)

        return () => document.removeEventListener('keydown', onKeyDown)
    }, []}

    return (
        <>
            <p>{renderCount++}</p>
            <p>{counter}</p>
        </>
    )
}

export default MyApp

GitHub

View Github