Skip to content

Commit

Permalink
feat: 🎸 add useRenderProp hook
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Oct 29, 2018
1 parent 5fe7925 commit 2d85c61
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
- [`useGetSet`](./docs/useGetSet.md) — returns state getter `get()` instead of raw state.
- [`useGetSetState`](./docs/useGetSetState.md) — as if [`useGetSet`](./docs/useGetSet.md) and [`useSetState`](./docs/useSetState.md) had a baby.
- [`useObservable`](./docs/useObservable.md) — tracks latest value of an `Observable`.
- [`useRenderProp`](./docs/useRenderProp.md) — extracts value from a render-prop or a FaCC.
- [`useSetState`](./docs/useSetState.md) — creates `setState` method which works like `this.setState`. [![][img-demo]](https://codesandbox.io/s/n75zqn1xp0)
- [`useToggle` and `useBoolean`](./docs/useToggle.md) — tracks state of a boolean.
- [`useCounter` and `useNumber`](./docs/useCounter.md) — tracks state of a number.
Expand Down
31 changes: 31 additions & 0 deletions docs/useRenderProp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# `useRenderProp`

Extracts a value from render-prop or FaCC component.


## Usage

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

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

const Demo = () => {
const [fragment1, [value1]] = useRenderProp(<FaCC />);
const [fragment2, [value2]] = useRenderProp(<RenderProp />);

return (
<>
{fragment1}
{fragment2}
<div>FaCC: {value1}</div>
<div>Render prop: {value2}</div>
</>
);
};
```
31 changes: 31 additions & 0 deletions src/__stories__/useRenderProp.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {storiesOf} from '@storybook/react';
import * as React from 'react';
import {useRenderProp} from '..';
import ShowDocs from '../util/ShowDocs';

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

const Demo = () => {
const [fragment1, [value1]] = useRenderProp(<FaCC />);
const [fragment2, [value2]] = useRenderProp(<RenderProp />);

return (
<>
{fragment1}
{fragment2}
<div>FaCC: {value1}</div>
<div>Render prop: {value2}</div>
</>
);
};

storiesOf('useRenderProp', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useRenderProp.md')} />)
.add('Demo', () =>
<Demo/>
)
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import useObservable from './useObservable';
import useOrientation from './useOrientation';
import useOutsideClick from './useOutsideClick';
import useRaf from './useRaf';
import useRenderProp from './useRenderProp';
import useSetState from './useSetState';
import useSize from './useSize';
import useSpeech from './useSpeech';
Expand Down Expand Up @@ -72,6 +73,7 @@ export {
useOrientation,
useOutsideClick,
useRaf,
useRenderProp,
useSetState,
useSize,
useSpeech,
Expand Down
29 changes: 29 additions & 0 deletions src/useRenderProp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';
import {useState, useCallback} from './react';
import createMemo from './createMemo';

const useRenderProp = (element: React.ReactElement<any>): [React.ReactElement<any>, any[]] => {
if (process.env.NODE_ENV !== 'production') {
if (!React.isValidElement(element)) {
throw new TypeError(
'useRenderProp element to be a valid React element ' +
'such as <MyRenderProp />.'
);
}
}

const [state, setState] = useState<any[]>([]);
const useSetState = createMemo((...args) => setState(args));
const render = useCallback((...args) => {
useSetState(...args);
return null;
}, []);
const cloned = React.cloneElement(element, {
render,
children: render,
});

return [cloned, state];
};

export default useRenderProp;

0 comments on commit 2d85c61

Please sign in to comment.