如何在React Context API的useEffect钩子中dispatch action?
How to Access Context Dispatch in useEffect (Instead of Consumer in Return)
Got it, let's fix this for you. Here's how you can access dispatch in your useEffect hook without relying on wrapping things in Consumer in the return statement:
Step 1: Export the Context from StateProvider.js
First, you need to export the Context you created so components can use the useContext hook to access its value. Also, there's a critical bug in your SET_USER reducer case that we'll fix (you were overwriting the entire state instead of merging it):
import React, { Component } from 'react'; // Export the Context to use with useContext hook export const Context = React.createContext(); // 1. 选择器 export const getSubtotal = (basket)=> basket?.reduce((amount,item)=> item.price + amount ,0); // 2. 归约器 const reducer = (state,action)=>{ switch(action.type){ case 'ADD_TO_BASKET' : return{ basket : [action.payload, ...state.basket], }; case 'DELETE_FROM_BASKET' : const index = state.basket.findIndex(item=>item.id === action.payload) let basketCopie = [...state.basket] basketCopie.splice(index,1) return{ basket : basketCopie }; case 'SET_USER' : // Important: Spread the original state to preserve basket data! return{ ...state, user : action.payload }; default : return state } } // 3. 提供者类 export class Provider extends Component { state = { basket : [], user : null, dispatch : action=> this.setState(state=> reducer(state,action)) } render() { return ( <Context.Provider value={this.state} > {this.props.children} </Context.Provider> ); } } // 4. 消费者 export const Consumer = Context.Consumer;
Step 2: Use useContext Hook in Your App Component
Now in your App component, import the Context and use the useContext hook to pull out the dispatch method directly. This lets you use it inside useEffect (or anywhere else in the component):
import React, { useEffect, useContext } from 'react'; import { Context } from './StateProvider'; // Import the exported Context function App() { // Get dispatch from the Context using useContext const { dispatch } = useContext(Context); useEffect(() => { auth.onAuthStateChanged(authUser => { if(authUser){ dispatch({ type : 'SET_USER', payload : authUser }) } else{ dispatch({ type : 'SET_USER', payload : null }) } }) }, [dispatch]) // Add dispatch to dependencies to ensure correct behavior return( {/* Your component JSX goes here */} ) }
Why This Works
- The
useContexthook lets you access the Context value directly in the body of your function component, no need to wrap your JSX inConsumer. - We fixed the
SET_USERreducer case to spread the original state (...state) so you don't lose thebasketdata when updating the user. - Adding
dispatchto theuseEffectdependency array ensures the hook uses the latest version ofdispatch(though in your current setup,dispatchis stable since it's defined once in the Provider's state, but it's good practice to include it).
内容的提问来源于stack exchange,提问作者bilalo
相关产品推荐
相关产品推荐

