-3

I ask for help with the Redux-saga, namely with refactoring the code below. Any ideas or explanations are welcome. The code below gets a list of hotels from the API on request with parameters from the function. It also has a check to see if data is currently being loaded or not at all. If the data is received, the action creator set Hotels is successfully executed. Thanks in advance for your reply.

hotels.js

export const getHotels = (cityName = 'London', date = currentDate(), days = 1, limit = 30) => {
return async (dispatch) => {
    dispatch(setIsFetching(true))
    dispatch(setIsEmpty(false))
    try {
        const response = await axios.get(`http://engine.hotellook.com/api/v2/cache.json?location=${cityName}&currency=rub&checkIn=${date}&checkOut=${addDays(date, days)}&limit=${limit}`)
        response.data.length === 0 ? dispatch(setIsEmpty(true)) : dispatch(setHotels(response.data))
    }
    catch (e) {
        dispatch(setIsEmpty(true))
    }
}

hotelsReducer.js

const SET_HOTELS = "SET_HOTELS";
const SET_IS_FETCHING = "SET_IS_FETCHING";
const SET_IS_EMPTY = "SET_IS_EMPTY";

const defaultState = {
  hotels: [],
  isFetching: true,
  isEmpty: false,
};

export const hotelsReducer = (state = defaultState, action) => {
  switch (action.type) {
    case SET_HOTELS:
      return {
        ...state,
        hotels: action.payload,
        isFetching: false,
      };
    case SET_IS_FETCHING:
      return {
        ...state,
        isFetching: action.payload,
      };
    case SET_IS_EMPTY:
      return {
        ...state,
        isEmpty: action.payload,
      };
    default:
      return state;
  }
};

export const setHotels = (results) => {return { type: SET_HOTELS, payload: results }};
export const setIsFetching = (bool) => {return { type: SET_IS_FETCHING, payload: bool }};
export const setIsEmpty = (bool) => {return { type: SET_IS_EMPTY, payload: bool }};
3
  • 1
    Can you be more specific? Did you start writing the saga, but then realize there's something you don't know how to do in a saga? Commented Apr 10, 2022 at 14:18
  • 1
    You are aware that generally the Redux team advises against sagas for most things unless you have a really complex use case that actually warrants the use of saga? Data fetching is usually not one of those use cases. You should probably use things in the order "RTK Query", "createAsyncThunk"/"thunk", "listenerMiddleware" and only if none of those did what you need, you should consider saga. redux.js.org/style-guide/style-guide/…
    – phry
    Commented Apr 10, 2022 at 15:04
  • I use the saga against my will) The test task for work involves writing part of the asynchronous actions using the saga. Saga seemed to me too complicated than a thunk. I updated my post with reducer.js. I just want to save this logic and remake this thunk-code into saga one
    – mondevyat
    Commented Apr 10, 2022 at 15:50

1 Answer 1

0

The saga is going to be very similar, you just need to replace the thunk with a new action that will trigger the saga:

import { put, takeLatest } from "redux-saga/effects";

function* fetchHotelsSaga() {
  yield put(setIsFetching(true));
  yield put(setIsEmpty(false));
  try {
    const response = yield axios.get(`http://engine.hotellook.com/api/v2/cache.json?location=${cityName}&currency=rub&checkIn=${date}&checkOut=${addDays(date, days)}&limit=${limit}`);
    response.data.length === 0
      ? yield put(setIsEmpty(true))
      : yield put(setHotels(response.data));
  } catch (e) {
    yield put(setIsEmpty(true));
  }
}

function* hotelsSaga() {
  // FETCH_HOTELS is a type for the new action that will be dispatched instead of the thunk
  yield takeLatest(FETCH_HOTELS, fetchHotelsSaga);
}
1
  • Thank you so much! You really saved me, dude)
    – mondevyat
    Commented Apr 12, 2022 at 9:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.