@@ -62,7 +62,6 @@ const App = () => {
6262 );
6363};
6464```
65-
6665### Example
6766
6867[ Open in CodeSandbox] ( https://codesandbox.io/s/44m70xm70 )
@@ -72,6 +71,13 @@ const App = () => {
7271Just an alternative syntax to ` useState ` , because it doesn't need array destructuring.
7372It returns an object with ` value ` and a ` setValue ` method.
7473
74+ ``` typescript
75+ type UseStateful <T = any > = {
76+ value: T
77+ setValue: React .Dispatch <React .SetStateAction <T >>
78+ }
79+ ` ` `
80+
7581` ` ` jsx
7682const username = useStateful (" test" );
7783
@@ -113,10 +119,10 @@ const App = () => {
113119### useBoolean
114120
115121``` jsx
116- const showCounter = useBoolean (true );
122+ const [ showCounter , actions ] = useBoolean (true );
117123```
118124
119- Methods :
125+ Actions :
120126
121127- ` toggle `
122128- ` setTrue `
@@ -134,7 +140,7 @@ const rotatingNumber = useNumber(0, {
134140});
135141```
136142
137- Methods :
143+ Actions :
138144
139145Both ` increase ` and ` decrease ` take an optional ` amount ` argument which is 1 by default, and will override the ` step ` property if it's used in the options.
140146
@@ -150,37 +156,62 @@ Options:
150156
151157### useInput
152158
153- ``` jsx
154- const newTodo = useInput (" " );
159+ This one is unique, since it returns tuple as a first element, where first element is ` value ` and second is ` hasValue `
160+ Second element is ` actions ` as usual
161+
162+ ``` typescript
163+ type UseInputActions = {
164+ setValue: UseStateful <string >[' setValue' ] // Look above
165+ onChange: (e : React .SyntheticEvent ) => void
166+ clear: () => void
167+ }
168+ type UseInput = [[string , boolean ], UseInputActions ]
155169` ` `
156170
157171` ` ` jsx
158- < input value = { newTodo . value } onChange = { newTodo . onChange } / >
172+ const [[ newTodo], actions] = useInput ( " " );
159173```
160174
161175``` jsx
162- < input {... newTodo .bindToInput } / >
163- < Slider {... newTodo .bind } / >
176+ < input value= {newTodo} onChange= {actions .onChange } / >
164177```
165-
166- Methods:
178+ Actions:
167179
168180- ` clear `
169- - ` onChange `
170- - ` bindToInput ` - binds the ` value ` and ` onChange ` props to an input that has ` e.target.value `
171- - ` bind ` - binds the ` value ` and ` onChange ` props to an input that's using only ` e ` in ` onChange ` (like most external components)
181+ - ` onChange ` - default native event.target.value handler
172182
173183Properties:
174184
175- - ` hasValue `
185+ - ` hasValue ` -
186+
187+ ### useBindToInput
188+
189+ Designed to be used in composition with ` useInput ` .
190+ First and second elements are the same as `useInput.
191+ Third are bindings to spread.
192+
193+ ``` jsx
194+ const [[newTodo ], actions , { nativeBind , valueBind }] = useBindToInput (useInput (" " ));
195+ ```
196+
197+ ``` jsx
198+ < input value= {newTodo} onChange= {actions .onChange } / >
199+ < input {... nativeBind} / >
200+ < Slider {... valueBind} / >
201+ ```
202+
203+ Actions:
204+
205+ - ` nativeBind ` - binds the ` value ` and ` onChange ` props to an input that has ` e.target.value `
206+ - ` valueBind ` - binds the ` value ` and ` onChange ` props to an input that's using only ` value ` in ` onChange ` (like most external components)
176207
177208### useArray
178209
179210``` jsx
180- const todos = useArray ([]);
211+ const [ todos , actions ] = useArray ([]);
181212```
182213
183- Methods :
214+ Actions :
184215
185216- ` add `
186217- ` clear `
@@ -198,14 +229,30 @@ all of them will be removed
198229 -3 | -4 | [1, 3, 2, 4, 5]
199230```
200231
232+ ### useMap
233+
234+ ``` jsx
235+ const [someMap , someMapActions ] = useMap ([[" key" , " value" ]]);
236+ const [anotherMap , anotherMapActions ] = useMap (new Map ([[" key" , " value" ]]));
237+ ```
238+
239+ Actions:
240+
241+ - ` set `
242+ - ` delete `
243+ - ` clear `
244+ - ` initialize ` - applies tuples or map instances
245+ - ` setValue `
246+
247+
201248## useSetState
202249
203250``` jsx
204- const { state , setState } = useSetState ({ loading: false });
251+ const [ state , setState ] = useSetState ({ loading: false });
205252setState ({ loading: true , data: [1 , 2 , 3 ] });
206253```
207254
208- Methods :
255+ Actions :
209256
210257- ` setState(value) ` - will merge the ` value ` with the current ` state ` (like this.setState works in React)
211258
@@ -230,3 +277,51 @@ const Counter = () => {
230277 );
231278};
232279```
280+
281+ ### Migration from v1 to v2
282+
283+ All value based hooks like ` useBoolean ` , ` useNumber ` etc. Are changed to
284+ be using arrays, since it's more safe for reference equality, and also
285+ makes it easier to use many ` useSmth ` without renaming ` value ` in destructuring.
286+
287+ So if you had
288+ ``` javascript
289+ const { value: showHeader , ... showHeaderActions } = useBoolean (true )
290+ const { value: showFooter , ... setShowFooterActions } = useBoolean (true )
291+ ```
292+ It will become
293+ ``` javascript
294+ const [showHeader , showHeaderActions ] = useBoolean (true )
295+ const [showFooter , showFooterActions ] = useBoolean (true )
296+ ```
297+
298+ Note that despite this code seems to be looking the same, it's not. Cause ` showHeaderActions ` in v1 will result
299+ in new object reference every rerender. While in v2 actions are memoized using ` useMemo ` and their reference will not
300+ change.
301+ It enables us passing ` actions ` down the props without useless re-renders, also it prevents ` useEffects ` and
302+ other hooks from re-run/new reference if autofix of ESLint rule ` react-hooks/extraneous-deps ` will add them as dependencies.
303+
304+ ### useInput migration
305+ Also big change to the ` useInput `
306+ If before you was not using ` bind ` and ` bindToInput ` from them, then using the same approach from above
307+ you will get what you want.
308+ But if you need bindings you need to compose ` useInput ` with ` useBindToInput ` like that:
309+ So if you had
310+ ``` jsx
311+ const { value , bindToInput , bind , onChange , hasValue } = useInput (" " )
312+
313+ < input value= {value} onChange= {onChange} / >
314+ < input {... bindToInput} / >
315+ {hasValue && < Slider {... bind} / > }
316+ ```
317+ It will become
318+ ``` jsx
319+ const [[value , hasValue ], actions , { nativeBind , valueBind }] = useBindToInput (useInput (" " ))
320+
321+ < input value= {value} onChange= {actions .onChange } / >
322+ < input {... nativeBind} / >
323+ {hasValue && < Slider {... valueBind} / > }
324+ ```
325+
326+ Note that first element in destructured array has tuple of ` [value, hasValue] ` since it's for values
327+ and second argument is for ` action ` e.g. only for functions.
0 commit comments