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

make-list-provider

v0.4.1

Published

Use hooks for an array of needful

Downloads

21

Readme

Make List Provider

Do you have a React hook that you need to call some number of times? Would you like to use React hooks to replace your list of classes with react natively? Do you just really like using lots of hooks and need to keep their output in a list?

Make a react list provider to store hook states and actions.

Usage

const [Provider, useItem, useList] = makeListProvider();

Provider

Provider for the list

  • onChange: called with a copy of a list when it is changed
return (
	<Provider
		onChange={setList}
	>
		<Component name="1" />
		{more.map(id => (
			<Component key={id} name={id} />
		))}
	</Provider>
);

useItem

Creates an entry in the Provider's list. Any value can be supplied as the argument. Changes to the value will update the Provider's callback and useList hook.

For ordered providers, useItem will return the index of the item in the ordered list.

export function Component({ name }) {
	const [state, setState] = useState(() => Math.random());

	const index = useItem(useMemo(() => ({
		name,
		state,
		setState,
	}), [name, state]));

	return null;
}

useList

Returns the Provider's list of values.

export function useItemByName(name) {
	const list = useList();
	const item = list.find(item => item.name === name);
	return item;
}

Variants

listProvider

The listProvider variant is the default behavior. The list is ordered based on React's useLayoutEffect call order. This is very useful for executing functions generated by JSX in order like layering on a Canvas.

const [CanvasProvider, useDraw, useDrawList] = makeListProvider();

function RenderCanvas() {
	const drawCallbacks = useDrawList();
	// ...
	return <canvas ref={ref} />
}

function DrawBox(props) {
	// ...
	useDraw(drawCallback);
}

function App() {
	return (
		<CanvasProvider>
			<RenderCanvas />
			<DrawBox rect={[1,2]} />
			<DrawBox rect={[2,3]} />
		</CanvasProvider>
	);
}

unorderedProvider

The unorderedProvider variant performs all the above functions without any ordering to the items. These will appear in any order they are called by React and are uncontrolled. This is useful for something like tracking many socket connections or local storage states.

const [SocketsProvider, useSocket, useSocketList] = makeUnorderedProvider();

function useSocketByName(name) {
	return useSocketList().find(socket => socket.name === name);
}

function Socket(props) {
	// ...
	useSocket(socket);
}

function App() {
	return (
		<SocketsProvider>
			<Socket port={8080} />
			<Socket port={8081} />
		</SocketsProvider>
	);
}

domProvider

The domProvider variant orders items based on the DOM subtree. A ref must be provided to each useItem as well as a parentRef to the Provider to observe updates. Using the DOM instead of the render cycle can reduce cpu usage on rarely changed elements. This is useful for custom select/option components

const [OptionsProvider, useOption, useOptionList] = makeDomProvider();

function Option(props) {
	const options = useOptionList();
	// ...
	const index = useOption(ref, value);
	return (
		<option ref={ref}>{index}</option>
	);
}

function App() {
	return (
		<select ref={ref}>
			<OptionsProvider parentRef={ref}>
				<Option />
				<Option />
			</OptionsProvider>
		</select>
	);
}

Notes

Ordering Children

Per useLayoutEffect's call order, a parent element will be ordered after it's children. To avoid unexpect results, you should not nest children under an element that is calling useItem. This behavior may change in the future.

Note: useLayoutEffect is used only in useListProvider. If you need more DOM driven ordering, try useDomProvider.

function Item({ children }) {
	useItem();
	return children;
}

function App() {
	return (
		<Provider>
			<Item />	// 1
			<Item>	// 3
				<Item />	// 2
			</Item>
			<Item />	// 4
		</Provider>
	);
}

License

Copyright (c) 2021, Michael Szmadzinski. (MIT License)