简体   繁体   中英

Correct way to dispatch redux action from request

I am using redux-thunk and I have the following action:

export const fetchUserInfo = () => dispatch => {
  return fetchCurrentUser()
    .then(user => {
      dispatch(retrieveUser(user));

      if (user && user.settings && user.settings.storePageId) {
        dispatch(getStoreById(user.settings.storePageId));
      }

      return user;
    })
    .catch(err => {
      console.error('Fetching userinfo failed', err);
      return Promise.reject(err);
    });
};

fetchCurrentUser is an api call defined as such:

export const fetchCurrentUser = () => authenticatedRequest('/customer');

Here is my authenticatedRequest:

import { logoutUser } from '../../actions/auth';
export const authenticatedRequest = (url, opts = {}, req = request) => {
  if (!cachedTokenType || !cachedAccessToken) {
    logoutUser() // I want this to happen!! :(

    return Promise.reject(
      new Error(
        'Missing token_type & access_token needed to perform this request'
      )
    );
  }

  const headers = { ...defaultOpts.headers, ...(opts.headers || {}) };

  const authedOpts = {
    ...opts,
    headers: {
      ...headers,
      Authorization: `${cachedTokenType} ${cachedAccessToken}`
    }
  };

  return req(url, authedOpts);
};

I want to be able to dispatch logoutUser() in my authenticatedRequest func so I dont have to duplicate this logic at all the places using authenticatedRequest. My problem is I dont know how to call a redux action from another file and when not in a react component with connect.

I want to be able to dispatch logoutUser() in my authenticatedRequest func...

I'd say that by achieving that, authenticatedRequest is doing more than one thing (authenticating and possibly logging users out). With time, complexity might increase and gets worst in case you want to change redux-thunk to something else.

Should you still need it, you can propagate dispatch so you can dispatch other actions:

const fetchCurrentUser = (dispatch) => authenticatedRequest(dispatch, '/customer')

const authenticatedRequest = (dispatch, url, opts = {}, req = request) => {
  if (YOUR_CONDITION) {
    dispatch(logoutUser())
  }
  ...
}

I personally wouldn't do that since it exposes dispatch to external calls. It's your choice though :)

Is it possible to handle logoutUser in fetchUserInfo action?

const authenticatedRequest = (url, opts = {}, req = request) => {
  if (YOUR_CONDITION) {
    return Promise.reject('LOGOUT')
  }
  ...
}

const fetchUserInfo = () => dispatch => {
  return fetchCurrentUser()
    .then(user => {
      ...
    })
    .catch(err => {
      if (err === 'LOGOUT') {
        dispatch(logoutUser())
      }
    })
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM