|
| 1 | +**useReducer hook accepts two arguments first argument is reducer function and second argument is initial app state then it return array with two elements - state and a dispatch function.** |
| 2 | + |
| 3 | +A Reducer Hook returns us a state object and a function to alter the state object. The function – called dispatch function – takes an action which has a type and an optional payload. All this information is used in the actual reducer function to distill a new state from the previous state, the action’s optional payload and type. |
| 4 | + |
| 5 | +Given the return value from **useReducer** is in the form object, I can do de-structuring to get the named-properties from that object by doing this. |
| 6 | + |
| 7 | +`const [state, dispatch] = useReducer(reducer, initialState)` |
| 8 | + |
| 9 | +By the [Official doc on the above array-destructuring synatax](https://reactjs.org/docs/hooks-state.html#tip-what-do-square-brackets-mean) |
| 10 | + |
| 11 | +It means that we’re making two new variables **state** and **dispatch**, where **state** is set to the first value returned by **useReducer**, and **dispatch** is the second. It is equivalent to this code: |
| 12 | + |
| 13 | +Every useReducer comes with its own dispatch function. |
| 14 | + |
| 15 | +The **useReducer** function is tightly coupled to its reducer and its dispatch function. We dispatch action objects to that reducer only. |
| 16 | + |
| 17 | +#### Now an example to convert a useState() to a useReducer() |
| 18 | + |
| 19 | +[https://reactjs.org/docs/hooks-reference.html#usestate](https://reactjs.org/docs/hooks-reference.html#usestate) |
| 20 | + |
| 21 | +**First useState implementation of a typical counter button** |
| 22 | + |
| 23 | +```js |
| 24 | +function Counter({ initialCount }) { |
| 25 | + const [count, setCount] = useState(initialCount); |
| 26 | + return ( |
| 27 | + <> |
| 28 | + Count: {count} |
| 29 | + <button onClick={() => setCount(initialCount)}>Reset</button> |
| 30 | + <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button> |
| 31 | + <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button> |
| 32 | + </> |
| 33 | + ); |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +Syntax |
| 38 | + |
| 39 | +`const [state, dispatch] = useReducer(reducer, initialArg, init)` |
| 40 | + |
| 41 | +An alternative to useState. Accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method. |
| 42 | + |
| 43 | +Here’s the counter example from the useState section, rewritten to use a reducer: |
| 44 | + |
| 45 | +```js |
| 46 | +const initialState = { count: 0 }; |
| 47 | + |
| 48 | +function reducer(state, action) { |
| 49 | + switch (action.type) { |
| 50 | + case "increment": |
| 51 | + return { count: state.count + 1 }; |
| 52 | + case "decrement": |
| 53 | + return { count: state.count - 1 }; |
| 54 | + default: |
| 55 | + throw new Error(); |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | +function Counter() { |
| 60 | + const [state, dispatch] = useReducer(reducer, initialState); |
| 61 | + return ( |
| 62 | + <> |
| 63 | + Count: {state.count} |
| 64 | + {/* dispatching the type of action*/} |
| 65 | + <button onClick={() => dispatch({ type: "increment" })}>+</button> |
| 66 | + <button onClick={() => dispatch({ type: "decrement" })}>-</button> |
| 67 | + </> |
| 68 | + ); |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +**A GENERAL EXAMPLE** |
| 73 | + |
| 74 | +**The dispatch function can be used to send an action to the reducer which would implicitly change the current state:** |
| 75 | + |
| 76 | +```JS |
| 77 | +const [todos, dispatch] = React.useReducer(todoReducer, initialTodos); |
| 78 | + |
| 79 | +dispatch({ type: 'DO_TODO', id: 'a' }); |
| 80 | +``` |
| 81 | + |
| 82 | +#### Compare it with how Redux dispatch() works |
| 83 | + |
| 84 | +Dispatches an action. This is the only way to trigger a state change. dispatch() is one of the 4 methods of redux-store. dispatch() is the method used to dispatch actions and trigger state changes to the store. So the way we take `actions` to the `store` is `dispatch` |
| 85 | + |
| 86 | +The store's reducing function will be called with the current getState() result and the given action synchronously. Its return value will be considered the next state. It will be returned from getState() from now on, and the change listeners will immediately be notified. |
| 87 | + |
| 88 | +There are a few rules of thumb to follow: If you state management doesn’t need all the Redux features, use useState, useReducer and useContext. If your state management needs Redux as one global state container with middleware, introduce Redux to your application to handle state logic in complex and large applications. |
| 89 | + |
| 90 | +- Use useState for basic and simple/small size applications. |
| 91 | +- Use useState + useReducer + useContext for advanced/medium size applications. |
| 92 | +- Use useState/useReducer + Redux for complex/large size applications. |
| 93 | + |
| 94 | +#### Further Reading |
| 95 | + |
| 96 | +- 1. [https://www.robinwieruch.de/redux-vs-usereducer/](https://www.robinwieruch.de/redux-vs-usereducer/) |
| 97 | +- 2. |
0 commit comments