# make-list-provider

> Use hooks for an array of needful

Latest version **0.4.1** (published 2023-11-24) · MIT license · 0 weekly downloads

## Install

```sh
npm install make-list-provider
pnpm add make-list-provider
yarn add make-list-provider
bun add make-list-provider
```

## Health

**Score 20/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities.

Warnings: low downloads; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.4.1 |
| Published | 2023-11-24 |
| First published | 2021-03-02 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 23.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Michael Szmadzinski |
| Maintainers | smujmaiku |

## Links

- npm: https://www.npmjs.com/package/make-list-provider
- Repository: https://github.com/smujmaiku/make-list-provider
- Homepage: https://github.com/smujmaiku/make-list-provider#readme
- Issues: https://github.com/smujmaiku/make-list-provider/issues
- npm.io page: https://npm.io/package/make-list-provider

## Dependencies (1)

- [just-observable](https://npm.io/package/just-observable.md) ^0.3.0

## Recent versions

- 0.4.1 (latest) — 2023-11-24
- 0.4.0 — 2023-11-24
- 0.3.0 — 2023-11-23
- 0.2.2 — 2021-07-29
- 0.2.1 — 2021-03-09
- 0.2.0 — 2021-03-08
- 0.1.0 — 2021-03-02

## 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

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

### Provider

Provider for the list

* `onChange`: called with a copy of a list when it is changed

```jsx
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.

```js
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.

```js
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.

```jsx
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.

```jsx
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

```jsx
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`.

```jsx
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)

---
_Source: https://npm.io/package/make-list-provider · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
