2

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;
  }
};
Aziz.G
  • 3,599
  • 2
  • 17
  • 35
  • Did you try to log action inside of the reducer? – hellogoodnight Apr 19 '21 at 17:53
  • Don't think this will solve it, but I know that you should put async function calls inside a local async funtion when calling them from useEffect. Look at this question here: https://stackoverflow.com/questions/53332321/react-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret – hellogoodnight Apr 19 '21 at 17:54
  • @hellogoodnight yes and it contains payload: array of 10 – Aziz.G Apr 19 '21 at 17:56
  • Where are you using the state? Show the code for the People component, which I assume uses this array please. – hellogoodnight Apr 19 '21 at 17:58
  • @hellogoodnight amazing question thank you my bad am using the `useEffect` in the wrong component Solved now thank you – Aziz.G Apr 19 '21 at 18:06

1 Answers1

1

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.

Shravan Dhar
  • 1,455
  • 10
  • 18