Tengo una tienda Redux configurada y estoy tratando de acceder al estado desde fuera de un componente React. Estoy usando store.getState() pero está devolviendo los valores de estado iniciales para todo en la tienda a pesar de que la tienda está llena con los datos correctos (visibles en la interfaz de usuario y las herramientas de desarrollo). Simplemente parece ser que cuando se importa la tienda y se accede al estado a través getState() , se devuelven los valores iniciales en lugar de lo que realmente está en la tienda. Código a continuación.
tienda.ts
import * as _ from "@reduxjs/toolkit/node_modules/redux-thunk"; import { Action, configureStore } from "@reduxjs/toolkit"; import { ThunkAction } from "redux-thunk"; import { useDispatch } from "react-redux"; import reducers from "./reducers"; const store = configureStore({ reducer: reducers, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false, }), }); export type AppDispatch = typeof store.dispatch; export type IRootState = ReturnType<typeof store.getState>; export type AppThunk = ThunkAction<void, IRootState, unknown, Action<string>>; // Export a hook that can be reused to resolve types export const useAppDispatch = () => useDispatch<AppDispatch>(); export default store;Servicio desde el que estoy llamando a la tienda:
import store from "store"; import { LoggingService } from "logger"; const logData(data) { const user = store.getState().user; LoggingService.log(user.email, data); } En el ejemplo anterior, store.getState().user devuelve un objeto, pero el email es nulo. Sin embargo, el email en realidad se completa como se puede ver en la interfaz de usuario y en las herramientas de desarrollo. Cualquier ayuda sería muy apreciada.
También tenga en cuenta que esta no es una aplicación SSR.
El store.getState() solo devuelve el estado actual de la tienda redux una vez. Los cambios posteriores al estado a través de la acción de envío no volverán a llamar a este método a menos que use subscribe(listener) .
En lugar de usar store.subscribe directamente, podemos escribir una utilidad de tienda observable personalizada. ¿Por qué? ver número 303
index.js :
export function toObservable(store) { return { subscribe({ onNext }) { let dispose = store.subscribe(() => onNext(store.getState())); onNext(store.getState()); return { dispose }; }, }; }¿Cómo usarlo? Escribamos una prueba para explicar esto:
import { combineReducers, createStore } from 'redux'; import { toObservable } from './'; const LoggingService = { log: console.log, }; describe('toObservable', () => { test('should pass', () => { function userReducer(state = { email: '' }, action) { switch (action.type) { case 'GET_USER_FULFILLED': return { ...state, ...action.payload }; default: return state; } } const store = createStore(combineReducers({ user: userReducer })); // create store observable somewhere, may be in the application initialization phase const store$ = toObservable(store); store$.subscribe({ onNext: (state) => LoggingService.log(state.user.email) }); // Later, dispatch action in component store.dispatch({ type: 'GET_USER_FULFILLED', payload: { email: 'example@gmail.com' } }); }); });Resultado de la prueba:
PASS redux-toolkit-example packages/redux-toolkit-example/examples/observer-store/index.test.ts toObservable ✓ should pass (23 ms) console.log at onNext (packages/redux-toolkit-example/examples/observer-store/index.test.ts:22:58) console.log example@gmail.com at onNext (packages/redux-toolkit-example/examples/observer-store/index.test.ts:22:58) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 2.937 s Como puede ver, cada vez que cambie el estado, se llamará al método onNext .
store.getState() no se actualiza inmediatamente. Debe usar el gancho useSelector en el Componente funcional para obtener el estado actualizado del redux. me gusta:
const user = useSelector((state) => state.user);