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

use-kv-state

v0.0.16

Published

1. **Simplified State Management**: This library provides a straightforward way to manage state with the `useKvState` hook, modeled after reacts own `useState` interface. This hook makes it easier to store, retrieve, and share values across all of your c

Downloads

12

Readme

Key-Value State Hooks

  1. Simplified State Management: This library provides a straightforward way to manage state with the useKvState hook, modeled after reacts own useState interface. This hook makes it easier to store, retrieve, and share values across all of your components in your entire application, without the need to setup context, providers, actions, reducers, prop mapping, etc.

  2. Persistent Storage: With the usePersistentKvState hook, you can easily persist key-value pairs in the browser's local storage. This allows your application to retain data across page refreshes or browser sessions, providing a seamless user experience.

  3. Scoped and Isolated Values: The useScopedKvState hook enables you to create scoped and isolated key-value pairs for each component instance. This is particularly useful when you have multiple instances of the same component and want to maintain separate states for each instance, preventing unintended state sharing.


Install

npm install use-kv-state

Quick Examples

Simple KV State Shared across 2 components

import { useKvState } from "./hooks/useKvState";

function MyFirstComponent() {
  const [count, setCount] = useKvState<string, number>("count", 0);

  return <button onClick={() => setCount(count + 1)}>Inc Count {count}</button>;
}

function MySecondComponent() {
  const [count] = useKvState<string, number>("count");

  return <p>Current count value: {count}</p>;
}

Dark mode button with persistence to localStorage

import { usePersistentKvState } from "../hooks/useKvState";

export function DarkModeButton() {
  const [darkMode, setDarkMode] = usePersistentKvState("darkMode", false);
  return (
    <button onClick={() => setDarkMode(!darkMode)}>
      Toggle Dark Mode {darkMode ? "Off" : "On"}
    </button>
  );
}

Next.js App Router dark mode persistent cookies to deal with flash of "light mode" and other server/client state sync tasks

import { usePersistentKvCookies } from "use-kv-state";

function DarkModeToggle() {
  const [darkMode, setDarkMode] = usePersistentKvCookies("darkMode", false);

  return (
    <button onClick={() => setDarkMode(!darkMode)}>
      Toggle Dark Mode: {darkMode ? "On" : "Off"}
    </button>
  );
}

Docs

This library exports the following hooks/functions for managing key-value stores:

  1. createKvStore
  2. useKvState
  3. usePersistentKvState
  4. useScopedKvState
  5. usePersistentKvCookies
  6. getPersistentKvCookies

Usage

useKvState

const [value, setValue] = useKvState(key, initialValue);
  • key: The key to identify the stored value.
  • initialValue (optional): The initial value to be stored.

Returns a tuple containing the current value and a function to update the value.

usePersistentKvState

const [value, setValue] = usePersistentKvState(key, initialValue);
  • key: The key to identify the stored value.
  • initialValue (optional): The initial value to be stored.

Similar to useKvState, but the values are persisted in the browser's local storage.

usePersistentKvCookies

const [value, setValue] = usePersistentKvCookies(key, initialValue);
  • key: The key to identify the stored value.
  • initialValue (optional): The initial value to be stored.

Similar to usePersistentKvState, but the values are persisted in the browser's local storage AND cookies. This is specifically targeted to work with Next.js App Router making local storage values accessible via cookies on the server with the server version of this function that works in server components: getPersistentKvCookies

getPersistentKvCookies

const value = getPersistentKvCookies(key, initialValue);
  • key: The key to identify the stored value.
  • initialValue (optional): The initial value to be stored.

Similar to usePersistentKvCookies, but for use directly inside server components. (Next.js App Router)

useScopedKvState

const [value, setValue] = useScopedKvState(key, initialValue);
  • key: The key to identify the stored value.
  • initialValue (optional): The initial value to be stored.

This hook provides a scoped key-value store, where the values are isolated based on the component instance. It's useful when you want to have separate instances of the same key-value pair in different components.

Example

import { useScopedKvState } from "../hooks/useKvState";

const options = [
  { id: 1, label: "Option 1", selected: false },
  { id: 2, label: "Option 2", selected: false },
  { id: 3, label: "Option 3", selected: false },
  { id: 4, label: "Option 4", selected: false },
];

export function MultiSelectionGroup() {
  const [optsState] = useScopedKvState(`selectedOptions`, options);

  return (
    <div>
      {optsState.map((option) => (
        <CheckItem key={option.id} option={option} />
      ))}
      <DisplaySelected />
    </div>
  );
}

export function CheckItem({ option }: any) {
  const [optsState, setOpts] = useScopedKvState<string, typeof options>(
    `selectedOptions`
  );

  const setSelected = (option: { id: number }) => {
    const newOptions = optsState.map((opt) => {
      if (opt.id === option.id) {
        return { ...opt, selected: !opt.selected };
      }
      return opt;
    });
    setOpts(newOptions);
  };

  return (
    <label key={option.id}>
      <input
        type="checkbox"
        checked={option.selected}
        onChange={() => setSelected(option)}
      />
      {option.label}
    </label>
  );
}

export function DisplaySelected() {
  const [optsState] = useScopedKvState<string, typeof options>(
    `selectedOptions`
  );

  if (!optsState) {
    return null;
  }

  return (
    <div>
      <h3>Selected Options</h3>
      {optsState
        .filter((opt) => opt.selected)
        .map((opt) => (
          <div key={opt.id}>{opt.label}</div>
        ))}
    </div>
  );
}

This example demonstrates how the useScopedKvState hook can be used to manage scoped and isolated state across multiple components in a multi-selection group scenario. The MultiSelectionGroup component renders a list of CheckItem components and a DisplaySelected component, all of which share the same state key ('selectedOptions') but maintain their own independent state. The CheckItem component updates the state when the checkbox is toggled, and the DisplaySelected component renders the list of selected options based on the current state. This showcases the power of the useScopedKvState hook in managing complex state scenarios across multiple components while ensuring proper isolation and scoping of the state.

Configuration

The createKvStore function accepts an optional configuration object with the following properties:

  • persistent (boolean, default: false): Determines if the values should be persisted in local storage.
  • setCookies (boolean, default: false): Determines if the values should be persisted in cookies (pairs with persistent)
  • localStorageKey (string, default: 'usePersistentKvStateDefaultLocalStorageKey'): The key prefix used for storing values in local storage.
  • trackAndIsolate (boolean, default: false): Determines if the values should be scoped and isolated based on the component instance.

These configuration options are used internally by the exported hooks.

Here's an example of how to use the createKvStore function to create a custom key-value store hook with specific configurations:

import { createKvStore } from './kvStore';

// Create a custom key-value store hook with persistent storage
const useMyPersistentKvStore = createKvStore({
  persistent: true,
  localStorageKey: 'myApp.kvStore',
});

// Create a custom key-value store hook with scoped and isolated values
const useMyIsolatedKvStore = createKvStore({
  trackAndIsolate: true,
});

function MyComponent() {
  // Use the custom persistent key-value store hook
  const [theme, setTheme] = useMyPersistentKvStore('theme', 'light');

  // Use the custom isolated key-value store hook
  const [count, setCount] = useMyIsolatedKvStore('count', 0);

  // ...
}

function AnotherComponent() {
  // Use the same custom persistent key-value store hook
  const [theme, setTheme] = useMyPersistentKvStore('theme', 'light');

  // Use the same custom isolated key-value store hook
  const [count, setCount] = useMyIsolatedKvStore('count', 0);

  // ...
}

In this example:

  1. We create a custom key-value store hook called useMyPersistentKvStore using createKvStore with the persistent option set to true and a custom localStorageKey prefix of 'myApp.kvStore'. This means that the values stored using this hook will be persisted in the browser's local storage under the key prefix 'myApp.kvStore'.

  2. We create another custom key-value store hook called useMyIsolatedKvStore using createKvStore with the trackAndIsolate option set to true. This means that the values stored using this hook will be scoped and isolated based on the component instance.

  3. In MyComponent, we use the useMyPersistentKvStore hook to manage the theme value, which will be persisted in local storage. We also use the useMyIsolatedKvStore hook to manage the count value, which will be isolated for each instance of MyComponent.

  4. In AnotherComponent, we use the same custom hooks as in MyComponent. The theme value will be shared and persisted across both components because it uses the same useMyPersistentKvStore hook. However, the count value will be isolated and separate for each component instance because it uses the useMyIsolatedKvStore hook.

By creating custom key-value store hooks using createKvStore, you can define specific configurations and reuse them across different components in your application. This allows for flexibility and consistency in managing key-value pairs with different behavior, such as persistence or isolation.