从不同的切片调用 reducer Redux Toolkit

Call reducer from a different slice Redux Toolkit

我有一个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 分离的情况下,有什么替代方法可以做到这一点?

您不想从 authSlice 调度 clearUser 操作。

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

另一种可能性是你让 userSlice 有一个额外的 reducer case 用于 logout 动作

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

这是基于你的 clearUser reducer(实际上不会改变状态)

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

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

我最终结合了 Zachary 的答案并引用了 SO post .

要有一个 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() 减速器:

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)。