Fetch API using Saga didn't give any response

Viewed 1182

all..

Iam new in react, I use react, redux and redux saga in my project. I just make simple api fetch using saga. but I don't know why the yield put command look did'nt work.

my code in bellow is my code:

types

export const GET_USERS_REQUESTED = "GET_USERS_REQUESTED";
export const GET_USERS_SUCCESS = "GET_USERS_SUCCESS";
export const GET_USERS_FAILED = "GET_USERS_FAILED";

actions

import * as type from "../types/users";

export function getUsers(users) {
  return {
    type: type.GET_USERS_REQUESTED,
    payload: users,
  };
};

reducers import * as type from "../types/users";

const initialState = {
  users: [],
  loading: false,
  error: null,
};

export default function users(state = initialState, action) {
  switch (action.type) {
    case type.GET_USERS_REQUESTED:
      return {
        ...state,
        loading: true,
      };
    case type.GET_USERS_SUCCESS:
      return {
        ...state,
        users: action.users,
        loading: false,
      };
    case type.GET_USERS_FAILED:
      return {
        ...state,
        loading: false,
        error: action.message,
      };

    default:
      return state;
  }
}

root reducers

import { combineReducers } from "redux";
import users from "./users";

const rootReducer = combineReducers({
  users: users,
});

export default rootReducer;

user saga

import { call, put, takeEvery } from "redux-saga/effects";
import * as type from "../redux/types/users";

function getApi() {
  return fetch("https://jsonplaceholder.typicode.com/users", {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  })
    .then((response) => {
      response.json();
    })
    .catch((error) => {
      throw error;
    });
}

function* fetchUsers(action) {
  try {
    const users = yield call(getApi());
    yield put({ type: type.GET_USERS_SUCCESS, users: users });
  } catch (e) {
    yield put({ type: type.GET_USERS_FAILED, message: e.message });
  }
}

function* userSaga() {
  yield takeEvery(type.GET_USERS_REQUESTED, fetchUsers);
}

export default userSaga;

root saga

import { all } from "redux-saga/effects";
import userSaga from "./users";

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

create store

import { createStore, applyMiddleware, compose } from "redux";
import rootReducer from "./reducers/index";
import createSagaMiddleware from "redux-saga";
import rootSaga from "../sagas/index";

const sagaMiddleware = createSagaMiddleware();
const store = compose(
  window.devToolsExtension && window.devToolsExtension(),
  applyMiddleware(sagaMiddleware)
)(createStore)(rootReducer);
sagaMiddleware.run(rootSaga);

export default store;

I don't know why my user saga looks like did'nt work. because loading state still have true value. Hopefully, anyone can help me.

Thanks in advance

2 Answers

You are calling your getApi and returning promise to the call itself. That call will do that for your. So just provide call with getApi like this:

...

function* fetchUsers(action) {
  try {
    const users = yield call(getApi); // <-- HERE IS THE CHANGE

    yield put({ type: type.GET_USERS_SUCCESS, users: users });
  } catch (e) {
    yield put({ type: type.GET_USERS_FAILED, message: e.message });
  }
}

...

Also you need to change your getApi since you are using fetch:

async function getApi() {
  const result = await fetch('https://jsonplaceholder.typicode.com/users', {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    },
  })
    .then((response) => {
      response.json();
    })
    .catch((error) => {
      throw error;
    });

  return result;
}

If you need to provide a variable to your getApi call you can just do:

const users = yield call(getApi, 'someValue');

And you getApi looks something like this:

async function getApi(someValue) {
  const result = await fetch(`https://jsonplaceholder.typicode.com/users/${someValue}`, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    },
  })
    .then((response) => {
      return response.json();
    })
    .catch((error) => {
      throw error;
    });

  return result;
}

When you use call you should not call() it. Type yield call(getApi, "in case you have arguments"). You should do that, when you are waiting for a promise

Related