问题
I have seen solutions for clearing/resetting the store after logout but did not understand how to implement the same functionality for the following way of setting up the redux store.
Store.js:
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
import authReducer from './ducks/authentication'
import snackbar from './ducks/snackbar'
import sidebar from './ducks/sidebar'
import global from './ducks/global'
import quickView from './ducks/quickView'
import profileView from './ducks/profileView'
const store = configureStore({
reducer: {
auth: authReducer,
snackbar,
sidebar,
global,
quickView,
profileView,
},
middleware: [...getDefaultMiddleware()],
})
export default store
Here is how all the reducers implemented using createAction and createReducer from @reduxjs/toolkit.
snackbar.js:
import { createAction, createReducer } from '@reduxjs/toolkit'
export const handleSnackbar = createAction('snackbar/handleSnackbar')
export const openSnackBar = (
verticalPosition,
horizontalPosition,
message,
messageType,
autoHideDuration = 10000
) => {
return async dispatch => {
dispatch(
handleSnackbar({
verticalPosition,
horizontalPosition,
message,
autoHideDuration,
messageType,
isOpen: true,
})
)
}
}
export const closeSnackbar = () => {
return dispatch => {
dispatch(handleSnackbar({ isOpen: false }))
}
}
const initialState = {
verticalPosition: 'bottom',
horizontalPosition: 'center',
message: '',
autoHideDuration: 6000,
isOpen: false,
messageType: 'success',
}
export default createReducer(initialState, {
[handleSnackbar]: (state, action) => {
const {
isOpen,
verticalPosition,
horizontalPosition,
message,
autoHideDuration,
messageType,
} = action.payload
state.isOpen = isOpen
state.verticalPosition = verticalPosition
state.horizontalPosition = horizontalPosition
state.message = message
state.autoHideDuration = autoHideDuration
state.messageType = messageType
},
})
回答1:
A simplified example with two reducers:
// actions and reducer for state.first
const resetFirst = () => ({ type: 'FIRST/RESET' });
const firstReducer = (state = initialState, action) => {
switch (action.type) {
// other action types here
case 'FIRST/RESET':
return initialState;
default:
return state;
}
};
// actions and reducer for state.second
const resetSecond = () => ({ type: 'SECOND/RESET' });
const secondReducer = (state = initialState, action) => {
switch (action.type) {
// other action types here
case 'SECOND/RESET':
return initialState;
default:
return state;
}
};
const rootReducer = combineReducers({
first: firstReducer,
second: secondReducer
});
// thunk action to do global logout
const logout = () => (dispatch) => {
// do other logout stuff here, for example logging out user with backend, etc..
dispatch(resetFirst());
dispatch(resetSecond());
// Let every one of your reducers reset here.
};
回答2:
As per Dan Abramov's answer, create a root reducer which will simply delegate the action to your main or combined reducer. And whenever this root reducer receives a reset type of action, it resets the state.
Example:
const combinedReducer = combineReducers({
first: firstReducer,
second: secondReducer,
// ... all your app's reducers
})
const rootReducer = (state, action) => {
if (action.type === 'RESET') {
state = undefined
}
return combinedReducer(state, action)
}
So, if you have configured your store with @reduxjs/toolkit's configureStore, it might look like this:
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
export default configureStore({
reducer: {
counter: counterReducer,
// ... more reducers
},
});
where configureStore
's first parameter reducer
accepts a function (which is treated as root reducer) or an object of slice reducers which is internally converted to root reducer using combineReducers.
So, now instead of passing object of slice reducers (shown above), we can create and pass root reducer by ourselves, here is how we can do it:
const combinedReducer = combineReducers({
counter: counterReducer,
// ... more reducers
});
Now, lets create a root reducer which does our reset job when needed:
const rootReducer = (state, action) => {
if (action.type === 'counter/logout') { // check for action type
state = undefined;
}
return combinedReducer(state, action);
};
export default configureStore({
reducer: rootReducer,
middleware: [...getDefaultMiddleware()]
});
Here is CodeSandbox
来源:https://stackoverflow.com/questions/59061161/how-to-reset-state-of-redux-store-when-using-configurestore-from-reduxjs-toolki