【问题标题】:fire redux action from extraReducers从 extraReducers 触发 redux 动作
【发布时间】:2021-05-26 21:09:50
【问题描述】:

首先,我知道(或者我想我已经读过)你永远不应该从减速器中触发动作。在我的情况下,我使用redux-oidc 来处理针对我的应用程序的身份验证。用户登录后,redux-oidc 会触发 redux-oidc/USER_FOUND 操作并在 state.oidc.user 切片中设置用户的个人资料。

登录后,我需要从我的数据库中查找不在 OIDC 响应中的有关用户的其他信息。目前,我正在从redux-oidc.CallbackComponent.successCallback 发射fetchUserPrefs thunk,它按预期工作。

我的问题是当用户有一个活动会话并打开一个新的浏览器,或者手动刷新页面并再次初始化应用程序时,回调没有被命中,所以额外的用户水合作用不会发生。 似乎我想做的是添加一个extraReducer 来监听redux-oidc/USER_FOUND 动作并触发thunk,但这会从reducer 触发一个动作。

有没有更好的方法来做到这一点?

import {createAsyncThunk, createSlice} from '@reduxjs/toolkit';
import { RootState } from '../../app/store';
import {User} from "oidc-client";

export const fetchUserPrefs = createAsyncThunk('user/fetchUserPrefs', async (user: User, thunkAPI) => {
    // the call out to grab user prefs
    // this works as expected when dispatched from the CallbackComponent.successCallback
    return user;
})

function hydrateUserState(state: any, action: any) {
    // set all the state values from the action.payload
    // this works as expected
}

export interface UserState {
    loginId: string;
    firstName: string;
    lastName: string;
    email: string;
    photoUrl: string;
}

const initialState: UserState = {
    loginId: '',
    firstName: '',
    lastName: '',
    email: '',
    photoUrl: '',
};

export const userSlice = createSlice({
    name: 'user',
    initialState,
    reducers: {
    },
    extraReducers: (builder) => {
        builder
            .addCase('redux-oidc/USER_FOUND', fetchUserPrefs) // I want to do this, or something like it
            .addCase(fetchUserPrefs.fulfilled, hydrateUserState)
            .addDefaultCase((state, action) => {})
    }
});

export const selectUser = (state: RootState) => state.user;
export default userSlice.reducer;

【问题讨论】:

  • 听起来像是自定义中间件的工作。

标签: javascript reactjs redux redux-toolkit redux-oidc


【解决方案1】:

您是正确的,您不能从 reducer 发送操作。您想监听要调度的动作并调度另一个动作作为响应。这是中间件的工作。您的中间件应如下所示:

import { USER_FOUND } from 'redux-oidc';
import { fetchUserPrefs } from "./slice";

export const oicdMiddleware = (store) => (next) => (action) => {
  // possibly dispatch an additional action
  if ( action.type === USER_FOUND ) {
    store.dispatch(fetchUserPrefs);
  }
  // let the next middleware dispatch the 'USER_FOUND' action
  return next(action);
};

您可以阅读custom middleware 上的文档以获取更多信息。

【讨论】:

    猜你喜欢
    • 2021-12-10
    • 2022-12-11
    • 2021-03-14
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多