【问题标题】:Call reducer from a different slice Redux Toolkit从不同的切片 Redux Toolkit 调用 reducer
【发布时间】:2021-01-24 23:18:11
【问题描述】:

我有一个authSlice

const authSlice = createSlice({
  name: 'authStore',
  initialState,
  reducers: {
    logout(state = initialState) {
      return { ...state, isAuthenticated: false };
    },
  },
  extraReducers: (builder) => {
    builder.addCase(login.fulfilled, (state, { payload }) => {
      state.isAuthenticated = true;
      localStorage.setItem('userId', payload.userId);
    });

    builder.addCase(login.pending, (state) => {
      state.isLoading = true;
    });

    builder.addCase(login.rejected, (state, { payload, error }) => {
      if (payload) {
        state.loginError = payload;
        state.isLoading = false;
      } else {
        state.loginError = error;
      }
    });
  },
});

还有一个userSlice

const userSlice = createSlice({
  name: 'userStore',
  initialState,

  reducers: {
    clearUser(state = initialState) {
      return { ...state };
    },
  },

  extraReducers: (builder) => {
    builder.addCase(getUser.fulfilled, (state, { payload }) => {
      state.user = payload;
      state.isLoading = false;
    });

    builder.addCase(getUser.pending, (state) => {
      state.isLoading = true;
    });

    builder.addCase(getUser.rejected, (state) => {
      state.isLoading = false;
    });
  },
});

我对我的代码有几个问题:

  1. 我如何从authSlice 拨打userSlice 中的clearUser()
  2. 这是一种好的做法还是一种反模式?
  3. 如果它是一种反模式,那么在保持authSliceuserSlice 分离的同时,还有什么替代方法可以做到这一点?

【问题讨论】:

    标签: reactjs typescript redux redux-toolkit


    【解决方案1】:

    您不希望从 authSlice 调度 clearUser 操作。

    您可以改为从 asyncThunk(或普通 thunk)调用它,但绝对不能从 reducer 调用。

    另一种可能性是您让userSlicelogout 操作提供了一个额外的减速器

    // This is assuming that you are exporting the actions from the authSlice
    builder.addCase(authActions.logout,(state=initialState)=>({...state}))
    

    这基于您的 clearUser 减速器(实际上不会改变状态)

    如果您想将状态重置为初始状态,则为:

    builder.addCase(authActions.logout,(state)=>initialState)
    

    【讨论】:

      【解决方案2】:

      我最终使用了 Zachary 的答案和引用 SO 帖子 here 的组合。

      要拥有一个通过一次调用清除所有状态的logout 函数,我需要创建一个包含清除状态的逻辑的rootReducer

      import { AnyAction, combineReducers, Reducer } from '@reduxjs/toolkit';
      import auth from './auth/authSlice';
      import user from './user/userSlice';
      
      const combinedReducer = combineReducers({
        auth,
        user,
      });
      
      export const rootReducer: Reducer = (state: RootState, action: AnyAction) => {
        if (action.type === 'authStore/logout') {
          localStorage.clear();
          state = {} as RootState;
        }
        return combinedReducer(state, action);
      };
      
      export type RootState = ReturnType<typeof combinedReducer>;
      

      authSlice 然后我创建了一个空的logout() reducer:

      const authSlice = createSlice({
        name: 'authStore',
        initialState,
        reducers: {
          logout: (state) => {
            /* declared here, handled in the root reducer: ../rootReducer.ts */
          },
        }
      })
      

      这最终在我的组件中使用,如下所示:

      import React from 'react';
      import { useDispatch } from 'react-redux';
      import { logout } from '../store/auth/authSlice';
      
      export const Home = () => {
        const dispatch = useDispatch();
        return <button onClick={() => dispatch(logout())}>Logout</button>;
      };
      
      

      如果我需要在注销过程中执行任何异步操作,我将不得不使用类似于 Zachary 在我的 rootReducer 中描述的方法(使用 Thunk)。

      【讨论】:

        猜你喜欢
        • 2020-12-13
        • 2020-04-14
        • 2021-05-05
        • 2022-01-18
        • 2020-04-24
        • 2021-03-03
        • 2023-01-04
        • 2015-12-28
        • 1970-01-01
        相关资源
        最近更新 更多