我正在构建一个,在其中我使用一个服务来进行所有的API调用。每当API返回401 - Unauthorized时,我都想向我的redux存储发送一个注销操作。
现在的问题是,我的api-服务没有反应组件,所以我无法获得对dispatch或actions的引用。我首先做的是导出存储并手动调用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现在的样子:
... 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;
};谢谢!
发布于 2017-04-12 12:11:26
如果您使用的是redux-thunk,则可以从动作创建者返回一个函数,该函数具有dispatch的参数:
const doSomeStuff = dispatch => {
fetch(…)
.then(res => res.json())
.then(json => dispatch({
type: 'dostuffsuccess',
payload: { json }
}))
.catch(err => dispatch({
type: 'dostufferr',
payload: { err }
}))
}另一种选择是使用中间件进行远程处理。这样做的方式是,中间可以测试一个动作的类型,然后将其转换为on或多个其他操作。请看一下here,它是相似的,即使基本上是关于动画的,答案是关于如何在远程请求中使用中间件的一些解释。
发布于 2017-04-12 12:15:51
您应该让您的api调用完全独立于redux。它应该返回一个承诺(就像它当前所做的那样),在愉快的情况下进行解析,并使用一个告诉状态的参数拒绝。有点像
if (statusAsString === '401') {
reject({ logout: true })
}
reject({ logout: false });然后在操作创建者代码中执行以下操作:
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());
}
);
};
}编辑:
如果不想到处编写错误处理代码,可以创建一个助手:
function logoutOnError(promise, dispatch) {
return promise.catch(({ logout }) => {
if(logout) {
dispatch(UserActions.logout());
}
})
}然后您就可以在您的行为创建者中使用它:
function fetchUsers() {
return function (dispatch) {
return logoutOnError(fetchWithAuth("/users", "GET"), dispatch).then(...)
}
}发布于 2017-04-17 08:37:18
也许您可以尝试使用中间件来捕获错误并分派注销操作,但在这种情况下,问题是您必须在操作创建者中分派错误,这需要检查日志状态。
api:抛出错误
if (statusAsString === '401') {
// !!!!!-> here I need to dispatch the logout action
throw new Error('401')
}动作创建者:从api捕获错误,以及分派错误操作
fetchSometing(ur)
.then(...)
.catch(err => dispatch({
type: fetchSometingError,
err: err
})中间件:捕获带有401消息的错误,并分派注销操作
const authMiddleware = (store) => (next) => (action) => {
if (action.error.message === '401') {
store.dispatch(UserActions.logout())
}
}https://stackoverflow.com/questions/43369009
复制相似问题