useReducer is not updating the sate with useEffect

Viewed 39

I want to fetch data using useReducer and useEffect getPeople is a function that return the result from https://swapi.dev/documentation#people when i console log results the data is fetching correctly but the state is not updated.

My functional component:

  export default function App () {
      const [state, dispatch] = useReducer(reducer, initialSate);
    
      useEffect(async () => {
        const { results } = await getPeople();
        dispatch({ type: FETCH_PEOPLE, payload: results });
      }, []);
    
      return (
        <>
          <GlobalStyles/>
          {state.loading
            ? <Loader size={'20px'} />
            : <>
          <Search></Search>
          <People />
          </>
          }
        </>
      );
    }

My reducer function:

export const reducer = (state = initialSate, action) => {
  switch (action.type) {
    case FETCH_PEOPLE:
      return {
        ...state,
        loading: false,
        results: action.payload,
        counter: state.counter
      };
    case INCREMENT_COUNTER:
      return {
        ...state,
        loading: true,
        counter: increment(state.counter)
      };
    case DECREMENT_COUNTER:
      return {
        ...state,
        loading: true,
        counter: decrement(state.counter)
      };
    default:
      return state;
  }
};
1 Answers

TLDR;

You need to wrap the async action in an IIFE:

useEffect(() => {
    (async() => {
        const { results } = await getPeople();
        dispatch({ type: FETCH_PEOPLE, payload: results });
    })();
}, []);

Details:
If you do the OP version in typescript then it will give out an error like:

Argument of type '() => Promise<void>' is not assignable to parameter of type 'EffectCallback'

The useEffect hook expects a cleanup function to be returned (optionally). But if we go ahead with OP's version, the async function makes the callback function return a Promise instead.

Related