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-hooked-component

v3.0.2

Published

Update your components props directly using callbacks from a hook

Downloads

119

Readme

use-hooked-component

Update your component's props directly using callbacks from a hook.

Installation

npm i use-hooked-component

A hooked component?

Normally to update a component's props you update some state for the props on the parent component which causes a re-render of the parent and all of it's children. useHookedComponent allows you to update the props directly without re-rendering everything. In its simplest form you use it like so:

const [HookedComponent, updateComponent, getValues] = useHookedComponent(SomeComponent);

It returns a component and a function you can use to update the component's props directly. It also returns a function as the last return value that you can use to get the props set using the update function, as well as any props set directly on the component.

Let's say you have a Spinner component that you show when loading some data or saving something. It has a single prop, visible, which you use to show or hide it. Rather than having a showSpinner or some such state on the parent, you can just call a function to update the Spinner directy. Only the Spinner will re-render. It's kind of like having methods for your components.

import { useEffect } from 'react';
import useHookedComponent from 'use-hooked-component';
import Spinner from './my/awesome/spinner';

function PageComponent(props) {
    const [HookedSpinner, updateSpinner] = useHookedComponent(Spinner);
    ...

    useEffect(() => {
        // Show the spinner - Only HookedSpinner re-renders
        updateSpinner({ visible: true });

        fetch('/path/to/data.json')
            .then(resp => resp.json())
            .then(data => {
                // Do something with the data

                // Hide the spinner - Only HookedSpinner re-renders
                updateSpinner({ visible: false });
            });
    }, []);

    return (<main>
        <HookedSpinner />
        ...
    </main>);
}

Just like a state update function from useState, you can pass a function to updateSpinner which will get passed an object of all of the props set using the hook as well as any props set on the component.

updateSpinner(current => ({ visible: !current.hookProps.visible })); // toggle the Spinner

You can still use the visible prop on the Spinner itself as a default, but when you update it using the updateSpinner function it will take precedence.

Defining your own setters

To have more control over updates, you can also define your own setter functions to update the component's props. You can pass a single setter, an array of setters, or an object. Each setter should return an object with all of the props to be set on the component. Props set directly on the component should not be included unless you want to override them. The getter function, not shown, will still be returned as the last return value.

const [HookedSpinner, showSpinner] = useHookedComponent(Spinner, visible => ({ visible }));

The above example defines a single setter. You can show the Spinner by calling showSpinner(true) and hide it by calling showSpinner(false).

// Array of setters
const [HookedSpinner, showSpinner, hideSpinner] = useHookedComponent(Spinner, [
    () => ({ visible: true }),
    () => ({ visible: false })
]);

OR

// Object containing the setters
const [HookedSpinner, { showSpinner, hideSpinner }] = useHookedComponent(Spinner, {
    showSpinner: () => ({ visible: true }),
    hideSpinner: () => ({ visible: false })
});

Now you can show the Spinner by calling showSpinner() and hide it by calling hideSpinner().

Getting the "current" object with custom setters

If you return a function from a custom setter, the function will be called and passed an object of all of the props set using the hook, as well as any props set on the component.

const [HookedSpinner, toggleSpinner] = useHookedComponent(Spinner, () => current => ({ 
    visible: !current.hookProps.visible
}));

The above example uses a single setter which automatically gets the current props passed to it. You can toggle the Spinner by calling toggleSpinner().

Wrapping up

Now you can take your hooked spinner and wrap it in its own hook.

import useHookedComponent from 'use-hooked-component';
import Spinner from './my/awesome/spinner';

function useSpinner() {
    return useHookedComponent(Spinner, {
        showSpinner: () => ({ visible: true }),
        hideSpinner: () => ({ visible: false })
    });
}

export default useSpinner;
import { useEffect } from 'react';
import useSpinner from './useSpinner';

function PageComponent(props) {
    const [Spinner, { showSpinner, hideSpinner }] = useSpinner();
    ...

    useEffect(() => {
        showSpinner();

        fetch('/path/to/data.json')
            .then(resp => resp.json())
            .then(data => {
                // Do something with the data

                hideSpinner();
            });
    }, []);

    return (<main>
        <Spinner />
        ...
    </main>);
}