Skip to content

Commit 91bee9a

Browse files
committed
feat: 🎸 add useAdopt hook
1 parent 2d85c61 commit 91bee9a

File tree

5 files changed

+89
-0
lines changed

5 files changed

+89
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
<br/>
7878
- [**State**](./docs/State.md)
7979
- [`createMemo`](./docs/createMemo.md) &mdash; factory of memoized hooks.
80+
- [`useAdopt`](./docs/useAdopt.md) &mdash; extract value from multiple render-prop (or FaCC) components.
8081
- [`useCallbag`](./docs/useCallbag.md) &mdash; tracks latest value of a callbag.
8182
- [`useGetSet`](./docs/useGetSet.md) &mdash; returns state getter `get()` instead of raw state.
8283
- [`useGetSetState`](./docs/useGetSetState.md) &mdash; as if [`useGetSet`](./docs/useGetSet.md) and [`useSetState`](./docs/useSetState.md) had a baby.

docs/useAdopt.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# `useAdopt`
2+
3+
Extracts a values from multiple render-prop or FaCC components.
4+
This hook is similar to [`useRenderProp`](./useRenderProp.md), but
5+
it allows to specify a named map of multiple render-prop elements
6+
from which to extract values.
7+
8+
9+
## Usage
10+
11+
```jsx
12+
import {useAdopt} from 'react-use';
13+
14+
const FaCC = ({children}) => {
15+
return children('VALUE-FaCC');
16+
};
17+
const RenderProp = ({render}) => {
18+
return render('VALUE-RenderProp');
19+
};
20+
21+
const Demo = () => {
22+
const [fragment, result] = useAdopt({
23+
facc: <FaCC/>,
24+
renderProp: <RenderProp/>,
25+
});
26+
27+
return (
28+
<>
29+
{fragment}
30+
<div>FaCC: {result.facc[0]}</div>
31+
<div>Render prop: {result.renderProp[0]}</div>
32+
</>
33+
);
34+
};
35+
```

src/__stories__/useAdopt.story.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {storiesOf} from '@storybook/react';
2+
import * as React from 'react';
3+
import {useAdopt} from '..';
4+
import ShowDocs from '../util/ShowDocs';
5+
6+
const FaCC = ({children}) => {
7+
return children('VALUE-FaCC');
8+
};
9+
const RenderProp = ({render}) => {
10+
return render('VALUE-RenderProp');
11+
};
12+
13+
const Demo = () => {
14+
const [fragment, result] = useAdopt({
15+
facc: <FaCC/>,
16+
renderProp: <RenderProp/>,
17+
});
18+
19+
return (
20+
<>
21+
{fragment}
22+
<div>FaCC: {result.facc[0]}</div>
23+
<div>Render prop: {result.renderProp[0]}</div>
24+
</>
25+
);
26+
};
27+
28+
storiesOf('useAdopt', module)
29+
.add('Docs', () => <ShowDocs md={require('../../docs/useAdopt.md')} />)
30+
.add('Demo', () =>
31+
<Demo/>
32+
)

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import createMemo from './createMemo';
2+
import useAdopt from './useAdopt';
23
import useAsync from './useAsync';
34
import useAudio from './useAudio';
45
import useBattery from './useBattery';
@@ -44,6 +45,7 @@ import useWindowSize from './useWindowSize';
4445

4546
export {
4647
createMemo,
48+
useAdopt,
4749
useAsync,
4850
useAudio,
4951
useBattery,

src/useAdopt.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import useRenderProp from './useRenderProp';
3+
4+
const useAdopt = <T extends {[key: string]: any[]}>(map: {[key in keyof T]: React.ReactElement<any>}): [React.ReactElement<any>, T] => {
5+
const keys = Object.keys(map);
6+
const fragments: React.ReactElement<any>[] = [];
7+
const result: T = {} as T;
8+
9+
keys.sort();
10+
for (const key of keys) {
11+
const [fragment, value] = useRenderProp(map[key]);
12+
fragments.push(React.cloneElement(fragment, {key}));
13+
result[key] = value;
14+
}
15+
16+
return [React.createElement(React.Fragment, null, ...fragments), result];
17+
};
18+
19+
export default useAdopt;

0 commit comments

Comments
 (0)