File tree 5 files changed +105
-0
lines changed
5 files changed +105
-0
lines changed Original file line number Diff line number Diff line change 71
71
<br />
72
72
<br />
73
73
- [ ** State** ] ( ./docs/State.md )
74
+ - [ ` useGetSet ` ] ( ./docs/useGetSet.md ) &mdash ; returns state getter ` get() ` instead of raw state.
74
75
- [ ` useObservable ` ] ( ./docs/useObservable.md ) &mdash ; tracks latest value of an ` Observable ` .
75
76
- [ ` useSetState ` ] ( ./docs/useSetState.md ) &mdash ; creates ` setState ` method which works like ` this.setState ` . [ ![ ] [ img-demo ]] ( https://codesandbox.io/s/n75zqn1xp0 )
76
77
- [ ` useToggle ` ] ( ./docs/useToggle.md ) &mdash ; tracks state of a boolean.
Original file line number Diff line number Diff line change
1
+ # ` useGetSet `
2
+
3
+ React state hook that returns state getter function instead of
4
+ raw state itself, this prevents subtle bugs when state is used
5
+ in nested functions.
6
+
7
+
8
+ ## Usage
9
+
10
+ Below example uses ` useGetSet ` to increment a number after 1 second
11
+ on each click.
12
+
13
+ ``` jsx
14
+ import {useGetSet } from ' react-use' ;
15
+
16
+ const Demo = () => {
17
+ const [get , set ] = useGetSet (0 );
18
+ const onClick = () => {
19
+ setTimeout (() => {
20
+ set (get () + 1 )
21
+ }, 1_000 );
22
+ };
23
+
24
+ return (
25
+ < button onClick= {onClick}> Clicked: {get ()}< / button>
26
+ );
27
+ };
28
+ ```
29
+
30
+ If you would do this example in a naive way using regular ` useState `
31
+ hook, the counter would not increment correctly if you click fast multiple times.
32
+
33
+ ``` jsx
34
+ const DemoWrong = () => {
35
+ const [cnt , set ] = useState (0 );
36
+ const onClick = () => {
37
+ setTimeout (() => {
38
+ set (cnt + 1 )
39
+ }, 1_000 );
40
+ };
41
+
42
+ return (
43
+ < button onClick= {onClick}> Clicked: {cnt}< / button>
44
+ );
45
+ };
46
+ ```
Original file line number Diff line number Diff line change
1
+ import * as React from 'react' ;
2
+ import { storiesOf } from '@storybook/react' ;
3
+ import { useGetSet } from '..' ;
4
+ import { useState } from '../react' ;
5
+ import ShowDocs from '../util/ShowDocs' ;
6
+
7
+ const Demo = ( ) => {
8
+ const [ get , set ] = useGetSet ( 0 ) ;
9
+ const onClick = ( ) => {
10
+ setTimeout ( ( ) => {
11
+ set ( get ( ) + 1 )
12
+ } , 1_000 ) ;
13
+ } ;
14
+
15
+ return (
16
+ < button onClick = { onClick } > Clicked: { get ( ) } </ button >
17
+ ) ;
18
+ } ;
19
+
20
+ const DemoWrong = ( ) => {
21
+ const [ cnt , set ] = useState ( 0 ) ;
22
+ const onClick = ( ) => {
23
+ setTimeout ( ( ) => {
24
+ set ( cnt + 1 )
25
+ } , 1_000 ) ;
26
+ } ;
27
+
28
+ return (
29
+ < button onClick = { onClick } > Clicked: { cnt } </ button >
30
+ ) ;
31
+ } ;
32
+
33
+ storiesOf ( 'useGetSet' , module )
34
+ . add ( 'Docs' , ( ) => < ShowDocs md = { require ( '../../docs/useGetSet.md' ) } /> )
35
+ . add ( 'Demo' , ( ) =>
36
+ < Demo />
37
+ )
38
+ . add ( 'DemoWrong' , ( ) =>
39
+ < DemoWrong />
40
+ )
Original file line number Diff line number Diff line change @@ -5,6 +5,7 @@ import useCounter from './useCounter';
5
5
import useCss from './useCss' ;
6
6
import useFavicon from './useFavicon' ;
7
7
import useGeolocation from './useGeolocation' ;
8
+ import useGetSet from './useGetSet' ;
8
9
import useHover from './useHover' ;
9
10
import useIdle from './useIdle' ;
10
11
import useLifecycles from './useLifecycles' ;
@@ -40,6 +41,7 @@ export {
40
41
useCss ,
41
42
useFavicon ,
42
43
useGeolocation ,
44
+ useGetSet ,
43
45
useHover ,
44
46
useIdle ,
45
47
useLifecycles ,
Original file line number Diff line number Diff line change
1
+ import { useState , useRef } from './react' ;
2
+
3
+ const useGetSet = < T > ( initialValue : T ) : [ ( ) => T , ( value : T ) => void ] => {
4
+ const [ _ , update ] = useState ( undefined ) ;
5
+ let state = useRef ( initialValue ) ;
6
+
7
+ const get = ( ) => state . current ;
8
+ const set = ( value : T ) => {
9
+ state . current = value ;
10
+ update ( undefined ) ;
11
+ } ;
12
+
13
+ return [ get , set ] ;
14
+ } ;
15
+
16
+ export default useGetSet ;
You can’t perform that action at this time.
0 commit comments