1 | import { useCallback, useState } from 'react';
|
2 |
|
3 | /**
|
4 | * Updates state, partial updates are merged into existing state values
|
5 | */
|
6 |
|
7 | /**
|
8 | * Mimics a React class component's state model, of having a single unified
|
9 | * `state` object and an updater that merges updates into the existing state, as
|
10 | * opposed to replacing it.
|
11 | *
|
12 | * ```js
|
13 | * const [state, setState] = useMergeState({ name: 'Betsy', age: 24 })
|
14 | *
|
15 | * setState({ name: 'Johan' }) // { name: 'Johan', age: 24 }
|
16 | *
|
17 | * setState(state => ({ age: state.age + 10 })) // { name: 'Johan', age: 34 }
|
18 | * ```
|
19 | *
|
20 | * @param initialState The initial state object
|
21 | */
|
22 | export default function useMergeState(initialState) {
|
23 | const [state, setState] = useState(initialState);
|
24 | const updater = useCallback(update => {
|
25 | if (update === null) return;
|
26 | if (typeof update === 'function') {
|
27 | setState(state => {
|
28 | const nextState = update(state);
|
29 | return nextState == null ? state : Object.assign({}, state, nextState);
|
30 | });
|
31 | } else {
|
32 | setState(state => Object.assign({}, state, update));
|
33 | }
|
34 | }, [setState]);
|
35 | return [state, updater];
|
36 | } |
\ | No newline at end of file |