Redux异步Effect中无需指定Payload访问rootState的问题及替代实现咨询
Let's break down what's happening here and how to fix this properly.
Why this.state returns undefined in your effect
In Redux (and frameworks built on top of it like Dva), effect functions don’t bind this to an instance that holds your app’s state. The framework is intentionally designed to pass critical dependencies—like payload, root state, and action-dispatching utilities—as explicit parameters, not through the this context. When you omit these parameters, this ends up pointing to an empty or global object, which is why this.state is undefined.
The correct approach: Use parameters to access state and trigger actions
Your first code snippet is on the right track by accepting rootState as a parameter, but there’s a key mistake: rootState is a data object storing your app’s state, not a collection of callable action methods. Calling rootState.doThis() won’t trigger an action—that’s not how Redux works. Instead, you need to dispatch actions using the framework’s provided tools.
For example, if you’re using Dva (which your code structure suggests), the second parameter of an effect is a context object with methods like put (to dispatch actions) and select (to retrieve state):
effects: { async doThisAndThat(_, { put, select }) { // Get the full root state of your app const rootState = await select(); console.log('Root state:', rootState); // Trigger your two actions correctly await put({ type: 'doThis' }); await put({ type: 'doThat' }); }, }
If you’re using plain Redux with Thunks, the pattern is similar—Thunk functions receive dispatch and getState directly as parameters:
const doThisAndThat = () => async (dispatch, getState) => { const rootState = getState(); console.log(rootState); // Dispatch your target actions dispatch(doThis()); dispatch(doThat()); };
Why Redux doesn’t support this.state for effects
Redux’s core design prioritizes predictability and testability. By passing dependencies like state and dispatch as explicit parameters:
- Your effect logic stays transparent—you can immediately see what it depends on
- Testing becomes simpler: you can mock
dispatchandgetStatewithout worrying about context binding quirks - You avoid the unpredictability of
thisin JavaScript, which can change based on how a function is invoked
Alternative reusable pattern
If you want to reuse this logic across multiple places, extract it into a standalone helper function:
// Helper function that takes dispatch and state as explicit arguments const runThisAndThat = (dispatch, rootState) => { console.log(rootState); dispatch(doThis()); dispatch(doThat()); }; // Use the helper in your effect effects: { async doThisAndThat(_, { dispatch, select }) { const rootState = await select(); runThisAndThat(dispatch, rootState); }, }
内容的提问来源于stack exchange,提问作者Marlo

