中间件中的调度方法不触发减速器

时间:2018-11-07 09:39:02

标签: reactjs redux middleware redux-thunk

从Redux Thunk中间件提供的参数中使用存储方法dispatch不会触发reducer。使用next()时可以正常工作,因为它会触发减速器。为什么会这样?

中间件

export default function createSlimAsyncMiddleware({
    dispatch,
    getState
}) {
    return next => action => {
    const {
        types,
        callAPI,
        shouldCallAPI = () => true,
    } = action;
    if (!actionIsValid(action)) next(action);
    if (shouldCallAPI(getState())) {
        return Promise.resolve(getState());
    }
    const [pendingType, successType, errorType] = types;
    dispatch({
        type: pendingType
    });
    return callAPI()
        .then(response => {
            dispatch({  // Does not work, use next()
                type: successType,
                payload: response,
            });
            console.log('call resolved with type', successType)
            return Promise.resolve(getState());
        })
        .catch(error => {
            dispatch({  // Does not work, use next()
                type: errorType,
                payload: error,
            });
            return Promise.reject(error);
        });
    };
}

商店

const store = createStore(
    appReducer,
    composeWithDevTools(applyMiddleware(
    thunk,
    createSlimAsyncMiddleware,
    routerMiddleware(history)
    ))
)

关于此回复https://stackoverflow.com/a/36160623/4428183dispatch也应该起作用。

1 个答案:

答案 0 :(得分:1)

您所包含的链接响应中对此进行了说明,但是调用logout(){ /* clear your localStorage token /* // redirect to login page } 将创建一个新操作,然后从头开始遍历整个中间件链。就您而言,这包括您要进行故障排除的中间件。据我所知,只有在传入操作被视为无效的情况下,您才调用 import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class JwtInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // add authorization header with jwt token if available let currentUser = JSON.parse(localStorage.getItem('currentUser')); if (currentUser && currentUser.token) { request = request.clone({ setHeaders: { Authorization: `Bearer ${currentUser.token}` } }); } return next.handle(request).do((event: HttpEvent<any>) => { if (event instanceof HttpResponse) { // do stuff with response if you want } }, (err: any) => { if (err instanceof HttpErrorResponse) { if (err.status === 401) { // redirect to the login route // or show a modal showing, we are redirecting to you login page. } } }); } } 。否则,后续的API调用会导致dispatch()再次被调用,无论调用是成功还是失败,因此该操作永远不会归结到reducer,因为它总是在中间件链的开头进行设置,并且永远不会前进通过next()

当您说此代码无效时,具体行为是什么?您的应用是否挂起?它会崩溃吗?因为这种情况实际上是在没有基本情况的情况下设置了一个递归函数,所以我敢打赌,您会看到“超出最大调用堆栈”之类的错误。

我想我想问的是为什么您需要使用dispatch()来获得请求结果,而不是使用next()来发送它们,或者为什么您没有以设置条件,该条件使用上一次调用的结果来确定是否再次调用该API。