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

@dteel/use-stored-reducer

v0.0.6

Published

useStoredReducer, kind of like useReducer except it will persist in localStorage. Will stay in sync with other hooks across your app and across brower windows.

Downloads

12

Readme

useStoredReducer Node.js CI

Description

useStoredReducer is a reducer hook that syncs to localStorage. If the localStorage value is changed, useStoredReducer updates to the new value. If another useStoredReducer hook in the application is utilizing the same keyName, the update is almost immediate.

For performance optimization, it optionally takes a hysterisis argument, which is how long it should wait before comitting the new value to localStorage (the change is made immediately to all the current app's hooks, but it will wait to write to localStorage). This prevents writing to the disk until the state has not changed in XXX milliseconds. If not specified, the localStorage is written to immediately. Writing immediately should be fine for simple values, but if using JSON.stringify/JSON.parse with large objects, it might make more sense to set the hysterisis to 100ms.

Add it to your project

Install the package from npm with

npm install @dteel/use-stored-reducer

And import it into one of your react components

import {useStoredReducer} from '@dteel/use-stored-reducer';

The hook

The hooks signature is

const [state, {current: dispatchRef}] = useStoredReducer(keyName, reducer, initialValue, storageObject, hysterisis=null)

Returned

  • state - the current state of the hook
  • dispatchRef - a ref to the dispatch function. To use, call dispatchRef.current('action', payload, callback)

Passed

  • keyName (string) - this is the key name the hook will use to read/write localStorage
  • reducer (callback) - pass in a function that handles the dispatch calls, example. This is different then reacts useReducer.
  • initialValue (any) - if the keyName is not found in localStorage, the initial state will be set to this, and it will be saved to localStorage
  • storageObject (optional, StorageObject) - what storage object to use. Can be localStorage, sessionStorage, or a custom object that implements Storage
  • hysterisis (optional, number) - this defines how long the hysterisis is before localStorage is written to. If not passed, or set to null, there is no hysterisis and state is stored to localStorage immediately.

Reducer function

The parameters to your reducer function are,

  • state - the current state
  • action - a string representing an action
  • payload - this is the optional data sent with the action from dispatch()
  • callback - this is a function supplied from dispatch()

Whatever you return from your reducer function is what the state gets set to.

Below is a simple example

function reducer(state, action, payload, callback) {
    switch (action) {
        case 'age':
            return {...state, age: Number(payload)};
        case 'name':
            return {...state, name: payload};
        case 'reset':
            return {age: 0, name: ''};
        case 'get':
            callback(state);
            return state;
        default:
            throw Error('undefined action');
    }
}

Small example component

import { useStoredReducer } from '@dteel/use-stored-reducer';

//The reducer function we pass to the hook, when you call dispatchRef.current(action, payload) 
//this function gets called with the current state and the action/payload you passed to it.
//what you return is what the state gets set to
function reducer(state, action, payload) {
    switch (action) {
        case 'age':
            return {...state, age: Number(payload)};
        case 'name':
            return {...state, name: payload};
        default:
            return state;
    }
}

export default function ExampleComponent(){
    //We're reading/writing to localStorage key 'person' with a hysterisis of 500ms
    //If someones typing, it wont save to storage until they have a 500ms break in key events
    const [state, {current: dispatch}] = useStoredReducer('person', reducer, {age: 0, name: ''}, localStorage, 500);
    return (
        <>
            <input type='text'  value={state?.age || ' '}   onChange={ (e) => dispatch('age', e.target.value) } />
            <input type='text'  value={state?.name || ' '}  onChange={ (e) => dispatch('name', e.target.value) } />
        </>
    );
}