Search code examples
javascriptreactjsreduxredux-sagause-effect

I cannot map on the data fetched from API


I fetch data from an API with Redux-Saga but I cannot use it when it updates state. It is probably because I am trying to access the data before it is loaded to the redux state.

//saga.js

import axios from 'axios';
import { put, takeLatest, all } from 'redux-saga/effects'
const URL = "https://api.staging.gamerarena.com/disputes/";

function* fetchInfo() {
  const res = yield axios.get(URL).then((response) => response);
  yield put({
    type: 'FETCH_INFO',
    payload: res
  })
}

function* actionWatcher() {
  yield takeLatest('GET_INFO', fetchInfo)
}

export default function* rootSaga() {
  yield all([
    actionWatcher(),
  ]);
}

Above, you can see that GET_INFO triggers fetch_info, but it updates the state after all other actions. I tried to fix it with useEffect but it did not help or I have not used it properly.

const DisputeCard = (props) => {

    const state = useSelector(state => state?.apiInfo?.apiInfo[0]?.results)
    const dispatch = useDispatch()

    useEffect(() => {

        dispatch(getInfo()) ; 
        console.log("State is ", state) // state returns undefined in the console

    }, [] );

The console that contains the defined error


Solution

  • Yes you can not access the data before its get fetched. Either you can wait for the data to get fetched or pass a callback function to your action.

    Use an0ther useEffect to wait for the data to get fetched, also you might have to wait for the data to render inside your component.

    const state = useSelector(state => state?.apiInfo?.apiInfo[0]?.results)
    const dispatch = useDispatch()
    
    useEffect(() => {
    
        dispatch(getInfo()) ; 
    
    }, [] );
    
    useEffect(() => {
        if(state) {
          console.log("State is ", state);
        }
    
    }, [state] );
    
    if(!state) {
     return null;
    }
    
    return (
      <div>{state}</div>
    )
    

    Or pass a callback to your action:

    export const getInfo = createAction("GET_INFO", (callback) => {
     return callback;
    })
    
    function* fetchInfo(action) {
     const callback = action.payload;
     const res = yield axios.get(URL).then((response) => response);
     callback(res)
     yield put({
      type: 'FETCH_INFO',
      payload: res
     })
     
     useEffect(() => {
    
      dispatch(
        getInfo((res) => {
         console.log("State is ", state) 
        })) ; 
       }, [] );
     }