I'd like to know what options do I have if I need to add some side-effects when using the useReducer hook.
For example, there is a TODO-app:
const initialState = {items: []};
const reducer = (state, action) => {
switch (action.type) {
case 'ADD':
return {
...state,
items: [...state.items, action.newItem]
};
default:
throw new Error();
}
};
const App = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<button onClick={() => dispatch({ type: 'ADD', newItem: 123 })}>
Add item
</button>
);
}
I need to save new items to the server. The question is: Where I should place this code?
(remember, that reducer should be pure)
The useEffect
hook is likely what you'd want to use. As the name suggests, it's precisely for doing side-effects per each render cycle. A small refactor to allow this within the component.
const App = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const [newItem, setNewItem] = useState(null);
useEffect(
() => {
// new item! dispatch state update, send to server, and reset newItem
dispatch({ type: 'ADD', newItem });
sendNewItemToServer(newItem);
setNewItem(null);
},
[newItem],
);
const newItemHandler = item => setNewItem(item);
return (
<button onClick={() => newItemHandler(123)}>
Add item
</button>
);
}
This is easy while your app is small, but as it get larger you may want to consider an app level event handling system, such as rxjs & redux/epics, redux sagas, redux thunks. These all rely on redux as the main source of app state truth and can handle the asynchronous calls to API's to send and retrieve data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With