mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
feat: 🎸 add useGetSet hook
This commit is contained in:
parent
deccec0070
commit
bfc30b99ab
@ -71,6 +71,7 @@
|
||||
<br/>
|
||||
<br/>
|
||||
- [**State**](./docs/State.md)
|
||||
- [`useGetSet`](./docs/useGetSet.md) — returns state getter `get()` instead of raw state.
|
||||
- [`useObservable`](./docs/useObservable.md) — tracks latest value of an `Observable`.
|
||||
- [`useSetState`](./docs/useSetState.md) — creates `setState` method which works like `this.setState`. [![][img-demo]](https://codesandbox.io/s/n75zqn1xp0)
|
||||
- [`useToggle`](./docs/useToggle.md) — tracks state of a boolean.
|
||||
|
||||
46
docs/useGetSet.md
Normal file
46
docs/useGetSet.md
Normal file
@ -0,0 +1,46 @@
|
||||
# `useGetSet`
|
||||
|
||||
React state hook that returns state getter function instead of
|
||||
raw state itself, this prevents subtle bugs when state is used
|
||||
in nested functions.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Below example uses `useGetSet` to increment a number after 1 second
|
||||
on each click.
|
||||
|
||||
```jsx
|
||||
import {useGetSet} from 'react-use';
|
||||
|
||||
const Demo = () => {
|
||||
const [get, set] = useGetSet(0);
|
||||
const onClick = () => {
|
||||
setTimeout(() => {
|
||||
set(get() + 1)
|
||||
}, 1_000);
|
||||
};
|
||||
|
||||
return (
|
||||
<button onClick={onClick}>Clicked: {get()}</button>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
If you would do this example in a naive way using regular `useState`
|
||||
hook, the counter would not increment correctly if you click fast multiple times.
|
||||
|
||||
```jsx
|
||||
const DemoWrong = () => {
|
||||
const [cnt, set] = useState(0);
|
||||
const onClick = () => {
|
||||
setTimeout(() => {
|
||||
set(cnt + 1)
|
||||
}, 1_000);
|
||||
};
|
||||
|
||||
return (
|
||||
<button onClick={onClick}>Clicked: {cnt}</button>
|
||||
);
|
||||
};
|
||||
```
|
||||
40
src/__stories__/useGetSet.story.tsx
Normal file
40
src/__stories__/useGetSet.story.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import * as React from 'react';
|
||||
import {storiesOf} from '@storybook/react';
|
||||
import {useGetSet} from '..';
|
||||
import {useState} from '../react';
|
||||
import ShowDocs from '../util/ShowDocs';
|
||||
|
||||
const Demo = () => {
|
||||
const [get, set] = useGetSet(0);
|
||||
const onClick = () => {
|
||||
setTimeout(() => {
|
||||
set(get() + 1)
|
||||
}, 1_000);
|
||||
};
|
||||
|
||||
return (
|
||||
<button onClick={onClick}>Clicked: {get()}</button>
|
||||
);
|
||||
};
|
||||
|
||||
const DemoWrong = () => {
|
||||
const [cnt, set] = useState(0);
|
||||
const onClick = () => {
|
||||
setTimeout(() => {
|
||||
set(cnt + 1)
|
||||
}, 1_000);
|
||||
};
|
||||
|
||||
return (
|
||||
<button onClick={onClick}>Clicked: {cnt}</button>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf('useGetSet', module)
|
||||
.add('Docs', () => <ShowDocs md={require('../../docs/useGetSet.md')} />)
|
||||
.add('Demo', () =>
|
||||
<Demo/>
|
||||
)
|
||||
.add('DemoWrong', () =>
|
||||
<DemoWrong/>
|
||||
)
|
||||
@ -5,6 +5,7 @@ import useCounter from './useCounter';
|
||||
import useCss from './useCss';
|
||||
import useFavicon from './useFavicon';
|
||||
import useGeolocation from './useGeolocation';
|
||||
import useGetSet from './useGetSet';
|
||||
import useHover from './useHover';
|
||||
import useIdle from './useIdle';
|
||||
import useLifecycles from './useLifecycles';
|
||||
@ -40,6 +41,7 @@ export {
|
||||
useCss,
|
||||
useFavicon,
|
||||
useGeolocation,
|
||||
useGetSet,
|
||||
useHover,
|
||||
useIdle,
|
||||
useLifecycles,
|
||||
|
||||
16
src/useGetSet.ts
Normal file
16
src/useGetSet.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {useState, useRef} from './react';
|
||||
|
||||
const useGetSet = <T>(initialValue: T): [() => T, (value: T) => void] => {
|
||||
const [_, update] = useState(undefined);
|
||||
let state = useRef(initialValue);
|
||||
|
||||
const get = () => state.current;
|
||||
const set = (value: T) => {
|
||||
state.current = value;
|
||||
update(undefined);
|
||||
};
|
||||
|
||||
return [get, set];
|
||||
};
|
||||
|
||||
export default useGetSet;
|
||||
Loading…
x
Reference in New Issue
Block a user