Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add side-effects when using "useReducer"?

Tags:

reactjs

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)

like image 607
J. Snow Avatar asked Mar 15 '20 15:03

J. Snow


1 Answers

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.

like image 150
Drew Reese Avatar answered Nov 01 '22 20:11

Drew Reese