Skip to content

Commit

Permalink
feat: 🎸 add useAdopt hook
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Oct 29, 2018
1 parent 2d85c61 commit 91bee9a
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -77,6 +77,7 @@
<br/>
- [**State**](./docs/State.md)
- [`createMemo`](./docs/createMemo.md) &mdash; factory of memoized hooks.
- [`useAdopt`](./docs/useAdopt.md) &mdash; extract value from multiple render-prop (or FaCC) components.
- [`useCallbag`](./docs/useCallbag.md) &mdash; tracks latest value of a callbag.
- [`useGetSet`](./docs/useGetSet.md) &mdash; returns state getter `get()` instead of raw state.
- [`useGetSetState`](./docs/useGetSetState.md) &mdash; as if [`useGetSet`](./docs/useGetSet.md) and [`useSetState`](./docs/useSetState.md) had a baby.
Expand Down
35 changes: 35 additions & 0 deletions docs/useAdopt.md
@@ -0,0 +1,35 @@
# `useAdopt`

Extracts a values from multiple render-prop or FaCC components.
This hook is similar to [`useRenderProp`](./useRenderProp.md), but
it allows to specify a named map of multiple render-prop elements
from which to extract values.


## Usage

```jsx
import {useAdopt} from 'react-use';

const FaCC = ({children}) => {
return children('VALUE-FaCC');
};
const RenderProp = ({render}) => {
return render('VALUE-RenderProp');
};

const Demo = () => {
const [fragment, result] = useAdopt({
facc: <FaCC/>,
renderProp: <RenderProp/>,
});

return (
<>
{fragment}
<div>FaCC: {result.facc[0]}</div>
<div>Render prop: {result.renderProp[0]}</div>
</>
);
};
```
32 changes: 32 additions & 0 deletions src/__stories__/useAdopt.story.tsx
@@ -0,0 +1,32 @@
import {storiesOf} from '@storybook/react';
import * as React from 'react';
import {useAdopt} from '..';
import ShowDocs from '../util/ShowDocs';

const FaCC = ({children}) => {
return children('VALUE-FaCC');
};
const RenderProp = ({render}) => {
return render('VALUE-RenderProp');
};

const Demo = () => {
const [fragment, result] = useAdopt({
facc: <FaCC/>,
renderProp: <RenderProp/>,
});

return (
<>
{fragment}
<div>FaCC: {result.facc[0]}</div>
<div>Render prop: {result.renderProp[0]}</div>
</>
);
};

storiesOf('useAdopt', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useAdopt.md')} />)
.add('Demo', () =>
<Demo/>
)
2 changes: 2 additions & 0 deletions src/index.ts
@@ -1,4 +1,5 @@
import createMemo from './createMemo';
import useAdopt from './useAdopt';
import useAsync from './useAsync';
import useAudio from './useAudio';
import useBattery from './useBattery';
Expand Down Expand Up @@ -44,6 +45,7 @@ import useWindowSize from './useWindowSize';

export {
createMemo,
useAdopt,
useAsync,
useAudio,
useBattery,
Expand Down
19 changes: 19 additions & 0 deletions src/useAdopt.ts
@@ -0,0 +1,19 @@
import * as React from 'react';
import useRenderProp from './useRenderProp';

const useAdopt = <T extends {[key: string]: any[]}>(map: {[key in keyof T]: React.ReactElement<any>}): [React.ReactElement<any>, T] => {
const keys = Object.keys(map);
const fragments: React.ReactElement<any>[] = [];
const result: T = {} as T;

keys.sort();
for (const key of keys) {
const [fragment, value] = useRenderProp(map[key]);
fragments.push(React.cloneElement(fragment, {key}));
result[key] = value;
}

return [React.createElement(React.Fragment, null, ...fragments), result];
};

export default useAdopt;

0 comments on commit 91bee9a

Please sign in to comment.