首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用thunk中间件从非反应组件中分派异步还原操作

使用thunk中间件从非反应组件中分派异步还原操作
EN

Stack Overflow用户
提问于 2017-04-12 12:03:27
回答 4查看 3.9K关注 0票数 3

我正在构建一个,在其中我使用一个服务来进行所有的API调用。每当API返回401 - Unauthorized时,我都想向我的redux存储发送一个注销操作。

现在的问题是,我的api-服务没有反应组件,所以我无法获得对dispatchactions的引用。我首先做的是导出存储并手动调用dispatch,但是当我在这里阅读How to dispatch a Redux action with a timeout?时,这似乎是一种糟糕的做法,因为它要求存储必须是单例,这使得在服务器上进行测试和呈现变得不可能,因为每个用户都需要不同的存储。

我已经在使用react-thunk (https://github.com/gaearon/redux-thunk)了,但是我把t see how I can inject分派到了非反应组件中。

我该怎么办?或者从react组件分派外部操作通常是一种不好的做法吗?这就是我的api.services.ts现在的样子:

代码语言:javascript
复制
... other imports
// !!!!!-> I want to get rid of this import
import {store} from '../';

export const fetchWithAuth = (url: string, method: TMethod = 'GET', data: any = null): Promise<TResponseData> => {
  let promise = new Promise((resolve, reject) => {
    const headers = {
      "Content-Type": "application/json",
      "Authorization": getFromStorage('auth_token')
    };
    const options = {
      body: data ? JSON.stringify(data) : null,
      method,
      headers
    };
    fetch(url, options).then((response) => {
      const statusAsString = response.status.toString();
      if (statusAsString.substr(0, 1) !== '2') {
        if (statusAsString === '401') {
          //  !!!!!-> here I need to dispatch the logout action
          store.dispatch(UserActions.logout());
        }
        reject();
      } else {
        saveToStorage('auth_token', response.headers.get('X-TOKEN'));
        resolve({
          data: response.body,
          headers: response.headers
        });
      }
    })
  });
  return promise;
};

谢谢!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-04-12 12:11:26

如果您使用的是redux-thunk,则可以从动作创建者返回一个函数,该函数具有dispatch的参数:

代码语言:javascript
复制
const doSomeStuff = dispatch => {
  fetch(…)
   .then(res => res.json())
   .then(json => dispatch({
     type: 'dostuffsuccess',
     payload: { json }
    }))
    .catch(err => dispatch({
      type: 'dostufferr',
      payload: { err }
     }))
}

另一种选择是使用中间件进行远程处理。这样做的方式是,中间可以测试一个动作的类型,然后将其转换为on或多个其他操作。请看一下here,它是相似的,即使基本上是关于动画的,答案是关于如何在远程请求中使用中间件的一些解释。

票数 2
EN

Stack Overflow用户

发布于 2017-04-12 12:15:51

您应该让您的api调用完全独立于redux。它应该返回一个承诺(就像它当前所做的那样),在愉快的情况下进行解析,并使用一个告诉状态的参数拒绝。有点像

代码语言:javascript
复制
if (statusAsString === '401') {
  reject({ logout: true })
}
reject({ logout: false });

然后在操作创建者代码中执行以下操作:

代码语言:javascript
复制
function fetchWithAuthAction(url, method, data) {

  return function (dispatch) {
    return fetchWithAuth(url, method, data).then(
      ({ data, headers }) => dispatch(fetchedData(data, headers)),
      ({ logout }) => {
        if(logout) {
          dispatch(UserActions.logout());
        } else {
          dispatch(fetchedDataFailed());
        }
    );
  };
}

编辑

如果不想到处编写错误处理代码,可以创建一个助手:

代码语言:javascript
复制
function logoutOnError(promise, dispatch) {
  return promise.catch(({ logout }) => {
    if(logout) {
      dispatch(UserActions.logout());
    }
  })
}

然后您就可以在您的行为创建者中使用它:

代码语言:javascript
复制
function fetchUsers() {
  return function (dispatch) {
    return logoutOnError(fetchWithAuth("/users", "GET"), dispatch).then(...)
  }
}
票数 0
EN

Stack Overflow用户

发布于 2017-04-17 08:37:18

也许您可以尝试使用中间件来捕获错误并分派注销操作,但在这种情况下,问题是您必须在操作创建者中分派错误,这需要检查日志状态。

api:抛出错误

代码语言:javascript
复制
        if (statusAsString === '401') {
          //  !!!!!-> here I need to dispatch the logout action
          throw new Error('401')
        }

动作创建者:从api捕获错误,以及分派错误操作

代码语言:javascript
复制
    fetchSometing(ur)
      .then(...)
      .catch(err => dispatch({
        type: fetchSometingError,
        err: err 
       })

中间件:捕获带有401消息的错误,并分派注销操作

代码语言:javascript
复制
const authMiddleware = (store) => (next) => (action) => {
  if (action.error.message === '401') {
    store.dispatch(UserActions.logout())
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43369009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档