Solución:
Una forma de hacerlo sería escribir un reductor de raíz en su aplicación.
El reductor raíz normalmente delegaría el manejo de la acción al reductor generado por combineReducers()
. Sin embargo, siempre que recibe USER_LOGOUT
acción, devuelve el estado inicial de nuevo.
Por ejemplo, si su reductor de raíces se ve así:
const rootReducer = combineReducers({
/* your app’s top-level reducers */
})
Puedes cambiarle el nombre a appReducer
y escribe una nueva rootReducer
delegándole:
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
return appReducer(state, action)
}
Ahora solo necesitamos enseñar lo nuevo rootReducer
para volver al estado inicial después de USER_LOGOUT
acción. Como sabemos, se supone que los reductores devuelven el estado inicial cuando se llaman con undefined
como primer argumento, sin importar la acción. Usemos este hecho para despojar condicionalmente el acumulado state
como lo pasamos a appReducer
:
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
state = undefined
}
return appReducer(state, action)
}
Ahora, cuando sea USER_LOGOUT
incendios, todos los reductores se inicializarán de nuevo. También pueden devolver algo diferente de lo que hicieron inicialmente si lo desean porque pueden verificar action.type
así como.
Para reiterar, el nuevo código completo se ve así:
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
state = undefined
}
return appReducer(state, action)
}
Tenga en cuenta que no estoy mutando el estado aquí, simplemente estoy reasignando la referencia de una variable local llamada state
antes de pasarlo a otra función. La mutación de un objeto de estado sería una violación de los principios de Redux.
En caso de que esté utilizando redux-persist, es posible que también deba limpiar su almacenamiento. Redux-persist mantiene una copia de su estado en un motor de almacenamiento, y la copia del estado se cargará desde allí en la actualización.
Primero, debe importar el motor de almacenamiento apropiado y luego, analizar el estado antes de configurarlo en undefined
y limpie cada clave de estado de almacenamiento.
const rootReducer = (state, action) => {
if (action.type === SIGNOUT_REQUEST) {
// for all keys defined in your persistConfig(s)
storage.removeItem('persist:root')
// storage.removeItem('persist:otherKey')
state = undefined;
}
return appReducer(state, action);
};
Me gustaría señalar que el comentario aceptado por Dan Abramov es correcto, excepto que experimentamos un problema extraño al usar el paquete react-router-redux junto con este enfoque. Nuestra solución fue no establecer el estado en undefined
pero aún usa el reductor de enrutamiento actual. Entonces, sugeriría implementar la solución a continuación si está utilizando este paquete
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
const { routing } = state
state = { routing }
}
return appReducer(state, action)
}
Definir una acción:
const RESET_ACTION = {
type: "RESET"
}
Luego, en cada uno de sus reductores, asumiendo que está usando switch
o if-else
para manejar múltiples acciones a través de cada reductor. Voy a tomar el caso por un switch
.
const INITIAL_STATE = {
loggedIn: true
}
const randomReducer = (state=INITIAL_STATE, action) {
switch(action.type) {
case 'SOME_ACTION_TYPE':
//do something with it
case "RESET":
return INITIAL_STATE; //Always return the initial state
default:
return state;
}
}
De esta manera cada vez que llames RESET
acción, su reductor actualizará la tienda con el estado predeterminado.
Ahora, para cerrar la sesión, puede manejar lo siguiente:
const logoutHandler = () => {
store.dispatch(RESET_ACTION)
// Also the custom logic like for the rest of the logout handler
}
Cada vez que un usuario inicia sesión, sin una actualización del navegador. La tienda siempre estará por defecto.
store.dispatch(RESET_ACTION)
simplemente elabora la idea. Lo más probable es que tenga un creador de acciones para ese propósito. Una forma mucho mejor será que tengas un LOGOUT_ACTION
.
Una vez que envíe esto LOGOUT_ACTION
. Un middleware personalizado puede interceptar esta acción, ya sea con Redux-Saga o Redux-Thunk. Sin embargo, en ambos sentidos, puede enviar otra acción ‘RESET’. De esta manera, el cierre de sesión y el reinicio de la tienda se realizarán de forma sincrónica y su tienda estará lista para el inicio de sesión de otro usuario.