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-connected-state

v2.0.1

Published

Connect state across React components. No Context. No callbacks. No wrappers.

Downloads

12

Readme

use-connected-state

Hook to connect state chages across React components. No callbacks. No context. No wrappers.

Installation

npm install use-connected-state

useConnectedState

Usage

useConnectedState, along with useConnectedValue and useConnectedSetter, let you connect state changes across components anywhere in the tree. When state changes in one component, it will be updated in other components connected to the same state, triggering a re-render.

Let's say you have a Input component and another component that shows the number of characters the user entered. You could wrap these in a single component but they may not live by each other in the layout.

// input.jsx
import useConnectedState from 'use-connected-state';

function Input() {
    const [chars, setChars] = useConnectedState({ key: 'chars', default: '' });
    const onChange = (e) => {
        setChars(e.target.value);
    };

    return (<input type="text" onChange={onChange} value={chars} />);
}

export default Input;
// character-count.jsx
import { useConnectedValue } from 'use-connected-state';

function CharacterCount() {
    const chars = useConnectedValue({ key: 'chars', default: '' });

    return (<p>Character Count: {chars.length}</p>);
}

export default CharacterCount;

The Input component when used by itself will work like any normal functional component that uses useState. You can add the CharacterCount component anywhere in the tree it will automatically show the count of characters from the Input component.

Just like useState, useConnectedState returns the value and a setter function. Also just like useState, you can pass the setter function a function which will receive the previous (current really) value as the first argument, but it also gets 2 more arguments: an object containing all of the state in the current scope and a setter function that allows you to update any piece of state by its key.

Let's say we have a component that shows how many times a counter has been clicked.

// clicks.jsx
import { useConnectedValue } from 'use-connected-state';

function Clicks() {
    const clicks = useConnectedValue({ key: 'clicks', default: 0 });

    return (<div>Total Clicks: {clicks}</div>);
}

export default Clicks;

Our Counter component can update the clicks of the Clicks component.

// counter.jsx
function Counter() {
    const [count, setCount] = useConnectedState({ key: 'count', default: 0 });

    const increment = () => {
        setCount((val, results, setByKey) => {
            // Using results to get the current value of clicks
            setByKey('clicks', results.clicks + 1);

            return val + 1;
        });
    };

    const decrement = () => {
        setCount((val, results, setByKey) => {
            // Passing an updater function which gets the current value of clicks
            setByKey('clicks', currClicks => currClicks + 1);

            return val - 1;
        });
    };

    return (<div>
        <div>Count: {count}</div>
        <button onClick={increment}>Increment</button>
        <button onClick={decrement}>Decrement</button>
    </div>);
}

If the Clicks component does not exist the setByKey call is ignored allowing the Counter to still work.

State Config

useConnectedState hooks take an optional state config object.

Properties

| Name | Type | Default | Description | |------|------|---------|-------------| | key | string | __defaultKey__ | (Optional) A key for the state. Any componets using useConnectedState with the same key and scope will be updated when state with that key is updated. | | default | any | undefined | (Optional) The default state for the given key and scope. The first component for the given key and scope will set the default state for all that follow. Subsequent components do not even need to pass this. As with useState, you can pass a function which returns the default state and it will only be executed on the first render. | | state | any | undefined | (Optional) Deprecated - replaced by default which makes more sense. | | scope | string | __defaultScope__ | (Optional) Provides scope for the state. Allows multiple components use the same key for state but not cause updates to each other. | | passive | boolean | false | (Optional) Allows you to passively get and set state. When passive is true, updates to that state will not trigger a re-render of the component. Also, when true the hook returns 2 functions: one to get the current value and one to set the value. |

Other Hooks

If you just want set or get the value of state you can use useConnectedSetter or useConnectedValue respectively. These are named exports so you would import them like

import { useConnectedSetter } from 'use-connected-state';

They take the same state config object as useConnectedState. When using useConnectedSetter you probably don't want that component to update when that state changes since you're not using the value, so you may want to add passive: true to the config.

// click-count.jsx
import { useConnectedValue } from 'use-connected-state';

function ClickCount() {
    const clicks = useConnectedValue({ key: 'clicks', default: 0 });

    return (<div>Total Clicks: {clicks}</div>);
}

export default ClickCount;
// clicker.jsx
import { useConnectedSetter } from 'use-connected-state';

function Clicker() {
    const setClicks = useConnectedSetter({ key: 'clicks', default: 0, passive: true });

    const onClick = () => {
        setClicks(clicks => clicks + 1);
    };

    return (<button onClick={onClick}>Click Me</button>);
}

export default Clicker;

Getting All State

The getCurrentState(<scope>) method that returns all state for the optionally specified scope. If scope is not specified it returns the state for the default scope.