1.1.1 • Published 6 years ago

redux-enhancer v1.1.1

Weekly downloads
4
License
MIT
Repository
github
Last release
6 years ago

Redux Enhancer

What is it?

Tired of always copy pasting a lot of redux boilerplate everytime you create a new store, or handle an async action?

  • Automaticaly generate the state of your async actions!
  • Automaticaly generate reset store

But in depth?

Enhance your redux modules:

Async Call Redux Steps Schema

  • Automaticaly handling the start, loading, error or success, and reset Redux phases of your async calls
    • Four action types will be automaticaly created such as:
      {
        REQUEST: {
          SIGNUP: {
            START: `USER.REQUEST.SIGNUP.START`,
            SUCCESS: `USER.REQUEST.SIGNUP.SUCCESS`,
            FAILED: `USER.REQUEST.SIGNUP.FAILED`,
            RESET: `USER.REQUEST.SIGNUP.RESET`,
          },
        },
      }
    • Two states will be automaticaly added such as:
      {
        requests: {
          LOGIN: {
            loading: true,
            failed: false,
          },
        },
      }
    • Two selectors corresponding to the state will be automaticaly generated such as:
      {
        signupLoading: (state) => state.user.requests.LOGIN.loading,
        signupFailed: (state) => state.user.requests.LOGIN.failed,
      }
  • Adding a RESET_STORE action to your different stores re-initializing your stores to their defaultState
    • An action type and action creator are generated:
      { RESET_STORE: 'RESET_STORE' }
      { resetStore: () => ({ type: 'RESET_STORE' }) }  
    • Your enhanced reducer will handle automaticaly your stores reset when dispatching the action

How to use? Full example here

  1. In your redux module file(s) import the necessary enhancers:

    import { enhanceActionTypes, enhanceActionCreators,
      enhanceDefaultState, enhanceReducer, enhanceSelectors } from 'redux-enhancer';
    ...
  2. Create two variables, a string for the name of your store, an array of string in caps for your async calls:

    ...
    const storeName = 'USER';
    const asyncActionsNames = ['SIGNUP'];
    ...
  3. Enhance your action types by passing the storeName and asyncActionsNames:

    ...
    const actionTypes = {
      ...enhanceActionTypes(storeName, asyncActionsNames),
      LOGOUT: 'LOGOUT',
    };
    ...
  4. Enhance your action creators by passing the storeName, apiActionsNames and actionTypes:

    ...
    const actionCreators = {
      ...enhanceActionCreators(storeName, asyncActionsNames, actionTypes),
      requestSignupStart: signupInfo => ({
        type: actionTypes.REQUEST.SIGNUP.START,
        payload: signupInfo,
      }),
    };
    ...
  5. Enhance your default state by passing the asyncActionsNames:

    ...
    const defaultState = {
      ...enhanceDefaultState(asyncActionsNames),
    };
    ...
  6. Create your normal reducer and enhance it afterwards by passing the storeName:

    ...
    const basicReducer = (state, action) => {
      switch (action.type) {
        case actionTypes.REQUEST.SIGNUP.SUCCESS:
          return {
            ...state,
            token: action.payload.token,
          };
        default:
          return state;
      }
    };
    
    const reducer = (state = defaultState, action) =>
      enhanceReducer(storeName, state, action, defaultState, basicReducer);
    ...
  7. Enhance your selectors by passing the storeName and asyncActionsNames:

    ...
    const selectors = {
      ...enhanceSelectors(storeName, asyncActionsNames),
      token: (state) => state.user.token,
    };
    ...
  8. Use your newly generated actions and state inside your app:

    // In a container?
    const mapStateToProps = (state) => ({
      signupLoading: selectors.signupLoading(state),
      signupFailed: selectors.signupFailed(state),
    });
    const mapDispatchToProps = {
      startSignup: actionCreators.startSignup,
      resetSignup: actionCreators.resetSignup,
    };
    
    // With a saga for instance
    function* signupSaga(action) {
      try {
        const { email, password, nickname } = action.payload;
        const { token } = yield call(api.signup, email, password, nickname);
        yield put({ type: actionTypes.REQUEST.SIGNUP.SUCCESS, payload: { token } });
      } catch (err) {
        yield put({ type: actionTypes.REQUEST.SIGNUP.FAILED, payload: { err } });
      }
    }

Contributing

To be filled

Todo

  1. Rename the package to make it more explicit and less generic
  2. Check the licence
  3. Find a way to flow type the automaticaly created actions and selectors