从另一个slice Redux Toolkit调用reducer

时间:2020-10-09 21:17:15

标签: reactjs typescript redux redux-toolkit

我有一个library(shiny) library(plotly) ui <- fluidPage( fluidRow(style = "background-color:#000000;", plotlyOutput(outputId = "myplot") ) ) server <- function(input, output) { output$myplot <- renderPlotly({ mydata <- data.frame(x = rnorm(10), y = rnorm(10)) fig <- plot_ly(data = mydata, x = ~x, y = ~y) %>% layout(hovermode = "solid", xaxis = list(showspikes=TRUE, spikethickness = 2), paper_bgcolor = "transparent", # Looks ok if set to "black" plot_bgcolor = "transparent") }) } shinyApp(ui = ui, server = server)

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

我对自己的代码有一些疑问:

  1. 如何从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}}中呼叫clearUser()
  2. 这是一种好的做法还是一种反模式?
  3. 如果这是反模式,那么在保持userSliceauthSlice分离的同时,还有另一种方法吗?

2 个答案:

答案 0 :(得分:1)

您不想从authSlice调度clearUser操作。

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

另一种可能性是,使userSlice动作具有一个{red}的减速器情况。

logout

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

如果您想将状态重置为初始状态,应该是:

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

答案 1 :(得分:0)

我最终结合使用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()减速器:

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