Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Hooks - useReducer: Wait for reducer to finish before triggering a function

I have the component using useReducer Hooks:

const init = {
  statA: true,
  statB: true
};

const reducer = (state, action) => {
  switch (action.type) {
    case "ActionA":
      return { ...state, statA: !state.statA };
    case "ActionB":
      return { ...state, statB: !state.statB };
    default:
      return state;
  }
};

const App = () => {
  const [state, dispatch] = useReducer(reducer, init);

  const clickMe = () => {
    dispatch({ type: "ActionA" });
    dispatch({ type: "ActionB" });
    console.log(state);
  }

  return(
      <button onClick={() => clickMe()}>Click Me</button>
  );
};

When the button is clicked, the state will be changed. But when I view the log, it prints the previous state, not the current updated state.

//On the first click
//Expected
{ statA: false, statB: false }
//Reality
{ statA: true, statB: true }

//On the second click
//Expected
{ statA: true, statB: true }
//Reality
{ statA: false, statB: false }

I know that with setState, I can use callback to work with updated state. But with useReducer, I don't know how to work with the updated state. Is there any way to solve my problem?

like image 557
Trí Phan Avatar asked Apr 07 '19 13:04

Trí Phan


People also ask

Does useReducer trigger re render?

Quick summary ↬ In a React component, useState and useReducer can cause your component to re-render each time there is a call to the update functions.

Is useReducer dispatch async?

Introduction. React useReducer doesn't support async actions natively. Unlike Redux, there's no middleware interface, but hooks are composable. This is a tiny library to extend useReducer's dispatch so that dispatching async actions invoke async functions.

What does the reducer function do in useReducer?

A reducer: A function that returns some state data, triggered by an action type. An action: An object that tells the reducer how to change the state. It must contain a type property and can contain an optional payload property.

Is useReducer better than Redux?

Can useReducer replace Redux? The useReducer hook should be used in components that have complex logic behind it. It shows as the main confusion with the Redux library, because developers tend to think that useReducer could replace the state manager library. But in fact, its use should be restricted to components.


Video Answer


1 Answers

console.log(state) is side effect. Side effects belong to useEffect hook:

  const [state, dispatch] = useReducer(reducer, init);

  useEffect(() => {
    // a condition may be added in case it shouldn't be executed every time
    console.log(state);
  }, [state]);

  const clickMe = () => {
    dispatch({ type: "ActionA" });
    dispatch({ type: "ActionB" });
  }
like image 89
Estus Flask Avatar answered Oct 11 '22 11:10

Estus Flask