question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use `redux-saga-requests` instead of constants/actions/reducer/saga quadruple

See original GitHub issue

Is your feature request related to a problem? Please describe. The idea is to use redux-saga-requests. It helps avoid the boilerplate code for constants, actions, reducers and sagas for simple (and also more sophisticated) web requests.

Describe the solution you’d like An excerpt from the https://github.com/klis87/redux-saga-requests README

  import axios from 'axios';
- import { takeEvery, put, call } from 'redux-saga/effects';
+ import { createRequestInstance, watchRequests, requestsReducer } from 'redux-saga-requests';
+ import { createDriver } from 'redux-saga-requests-axios';

  const FETCH_BOOKS = 'FETCH_BOOKS';
- const FETCH_BOOKS_SUCCESS = 'FETCH_BOOKS_SUCCESS';
- const FETCH_BOOKS_ERROR = 'FETCH_BOOKS_ERROR';

- const fetchBooks = () => ({ type: FETCH_BOOKS });
- const fetchBooksSuccess = data => ({ type: FETCH_BOOKS_SUCCESS, data });
- const fetchBooksError = error => ({ type: FETCH_BOOKS_ERROR, error });
+ const fetchBooks = () => ({
+   type: FETCH_BOOKS,
+   request: {
+     url: '/books',
+     // you can put here other Axios config attributes, like method, data, headers etc.
+   },
+ });

- const defaultState = {
-   data: null,
-   pending: 0, // number of pending FETCH_BOOKS requests
-   error: null,
- };
-
- const booksReducer = (state = defaultState, action) => {
-   switch (action.type) {
-     case FETCH_BOOKS:
-       return { ...defaultState, pending: state.pending + 1 };
-     case FETCH_BOOKS_SUCCESS:
-       return { ...defaultState, data: action.data, pending: state.pending - 1 };
-     case FETCH_BOOKS_ERROR:
-       return { ...defaultState, error: action.error, pending: state.pending - 1 };
-     default:
-       return state;
-   }
- };
+ const booksReducer = requestsReducer({ actionType: FETCH_BOOKS });

- const fetchBooksApi = () => axios.get('/books');
-
- function* fetchBooksSaga() {
-   try {
-     const response = yield call(fetchBooksApi);
-     yield put(fetchBooksSuccess(response.data));
-   } catch (e) {
-     yield put(fetchBooksError(e));
-   }
- }
-
  function* rootSaga() {
-   yield takeEvery(FETCH_BOOKS, fetchBooksSaga);
+   yield createRequestInstance({ driver: createDriver(axios) });
+   yield watchRequests();
  }

Describe alternatives you’ve considered

Additional context It would also help to use GraphQL endpoints: https://github.com/klis87/redux-saga-requests/tree/master/packages/redux-saga-requests-graphql

PS: I would be willing to work on it as well.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
julienbencommented, Aug 29, 2019

Having less boilerplate code would be great and I think there’s a way to do this. I’m not sure we should do it with redux-saga-requests though.

A few thoughts on why:

  • It has a large API surface and long docs => Big learning curve
  • It has excellent coverage and might be well tested but is it used in production by any big teams? AFAIK, almost all our dependencies are industry-standards and have been vetted by large companies and exposed to millions of users.
  • It’s not entirely clear if this is a replacement for all the sagas you might need to write or if it only covers some use cases. And if all one does with redux-sagas is fetch data from an API, then using redux-sagas is total overkill in the first place.
  • It also “hides” some things. So, for example, you’re forced to consult its docs to know what your store looks like after coming out of a requestsReducer. Otherwise you might not know what keys are inside.

IMO, a “write less boilerplate” solution which might make more sense for us is one which simplifies the creation of the { actions, constants, reducer } tuple (without touching the sagas side of things).

I would love to find a tool which allows us to do something like this:

const initialState = {
  /* ... */
};

const { actions, constants, reducer } = magicalFunctionOfMyDreams(
  initialState,
  {
    FETCH_REPOS: {
      produce: store => {
        store.loading = true;
        store.error = false;
      },
    },
    FETCH_REPOS_SUCCESS: {
      // When you need to pass data in your action creator in addition to the type
      action: data => ({ data }),
      produce: (store, action) => {
        store.loading = false;
        store.error = false;
        store.data = action.data;
      },
    },
    FETCH_REPOS_ERROR: {
      produce: store => {
        store.loading = false;
        store.error = true;
      },
    },
  },
);

// Pass actions to your component, reducer for async injection and constants for watching in sagas or any other middleware
export {actions, constants, reducer};

(Btw, either as an alternative or in addition to the above, one could also write a generator which frees the dev from writing a lot of boilerplate.)

0reactions
lock[bot]commented, Nov 24, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found