Search code examples
reactjsreduxreact-reduxredux-saga

Redux-saga with redux-toolkit returning empty object and consoling the response shows promise{<pending>}


Hey guys I am a beginner and trying to learn redux-saga with redux-toolkit. I am getting an empty user object and when I consoled the axios response, it is showing all the data, but not in handler.

this is the code.

UserInfoSlice

import {createSlice} from '@reduxjs/toolkit';

export const userInfoSlice = createSlice({
    name: 'user',
    initialState: {
        user: {},
    },

    reducers: {
        getUser() {},

        setUser(state, action) {
            const userInfo = action.payload;
            console.log(userInfo)
            return {...state, ...userInfo};
        }
    },
})


export const {getUser, setUser} = userInfoSlice.actions;

export const selectUserInfo = state => state.user.user;

export default userInfoSlice.reducer;

store

import {configureStore, combineReducers, getDefaultMiddleware} from '@reduxjs/toolkit';
import createSagaMiddleware from "redux-saga";
import {watcherSaga} from '../saga/RootSaga';

import userinfoReducer from '../features/UserInfoSlice';

const sagaMiddleware = createSagaMiddleware();

const reducers = combineReducers({
    user: userinfoReducer,
});
const store = configureStore({
    reducer: reducers,
    middleware: [...getDefaultMiddleware({thunk: false}), sagaMiddleware]
});

sagaMiddleware.run(watcherSaga);

export default store;

rootsaga

import { takeLatest } from "redux-saga/effects";
import {handlegetUserInfo} from './handlers/UserInfo';
import {getUser} from '../features/UserInfoSlice';






export function* watcherSaga() {
    yield takeLatest(getUser.type, handlegetUserInfo)
}

userInfoHandler

import { call, put } from "redux-saga/effects";
import { requestGetUserInfo } from '../requests/UserInforequest';
import { setUser } from "../../features/UserInfoSlice";


export function* handlegetUserInfo() {
    try {
        const response = yield call(requestGetUserInfo);
        console.log(response)
        const { data } = response;
        console.log(data);
        yield put(setUser({ ...data }))    
    } catch(e) {
        console.log(e)
    }
}

userinforequest

import axiosInstance from '../../../axios';


export function* requestGetUserInfo() {
    return axiosInstance.get('api/user/')
}

please let me know what I have done wrong here and how to resolve this.?

Thank you


Solution

  • Generator vs. Async

    You are defining requestGetUserInfo as a generator function with function*. This means that you need to yield the result.

    export function* requestGetUserInfo() {
      return yield axios.get('api/user/');
    }
    

    Alternatively, you can define it as an async function and await the result.

    export async function requestGetUserInfo() {
      return await axios.get('api/user/');
    }
    

    Slice Shape

    Depending on the shape of your API response, there might be an issue in your setUser case reducer.

    The initialState of your userInfoSlice declares that this is an object with a property user. Your setUser reducer sets the properties from the action.payload userInfo as top-level properties of the state. This would only be ok your API returns an object with a property user. More likely, it returns the user object and you'd want to set this userInfo to the user property of your state.

    setUser(state, action) {
      const userInfo = action.payload;
      console.log("payload", userInfo);
      return { ...state, user: userInfo };
    }
    

    Code Sandbox Demo