mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
feat: 🎸 add useRenderProp hook
This commit is contained in:
parent
5fe7925cf0
commit
2d85c61ba8
@ -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.
|
||||
|
||||
31
docs/useRenderProp.md
Normal file
31
docs/useRenderProp.md
Normal file
@ -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
src/__stories__/useRenderProp.story.tsx
Normal file
31
src/__stories__/useRenderProp.story.tsx
Normal file
@ -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/>
|
||||
)
|
||||
@ -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';
|
||||
@ -72,6 +73,7 @@ export {
|
||||
useOrientation,
|
||||
useOutsideClick,
|
||||
useRaf,
|
||||
useRenderProp,
|
||||
useSetState,
|
||||
useSize,
|
||||
useSpeech,
|
||||
|
||||
29
src/useRenderProp.ts
Normal file
29
src/useRenderProp.ts
Normal file
@ -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;
|
||||
Loading…
x
Reference in New Issue
Block a user