Next.js自定义Hook中访问Redux Toolkit Dispatch报错求助
问题:Next.js自定义Hook中使用Redux dispatch报错
我在Next.js应用中实现了一个用于生成Axios实例的自定义Hook,想在其中使用dispatch,但碰到了如下错误:
Error: could not find react-redux context value; please ensure the component is wrapped in a Provider
Hook代码如下:
import axios from 'axios'; import { useRouter } from 'next/router' import { useAppDispatch } from '../store/hooks' import { stopLoading } from '../store/features/loadingSlice' const useAxiosInstance = () => { const dispatch = useAppDispatch() const router = useRouter() const instance = axios.create({ baseURL: 'http://localhost:4000' }); instance.defaults.withCredentials = true instance.interceptors.response.use((response) => { return response }, (error) => { if(error.response.status === 401 && window.location.href !== 'http://localhost:3000/') { router.push('/') dispatch(stopLoading()) } return Promise.reject(error) }) return instance } export default useAxiosInstance
解决方案
1. 确保应用被Redux Provider全局包裹
Redux的useDispatch(包括你自定义的useAppDispatch)依赖React Context,必须让整个应用组件树处于Provider的包裹下。在Next.js中,通常在_app.js/_app.tsx中配置:
import { Provider } from 'react-redux' import { store } from '../store' // 你的Redux store实例 import '../styles/globals.css' function MyApp({ Component, pageProps }) { return ( <Provider store={store}> <Component {...pageProps} /> </Provider> ) } export default MyApp
2. 仅在合法React上下文调用自定义Hook
useAxiosInstance作为自定义Hook,只能在React函数组件内部或者其他自定义Hook中调用,不能在普通函数、类组件,或者组件渲染流程之外的场景使用——这些环境无法访问Redux的Context。
3. 检查useAppDispatch的定义正确性
确保store/hooks.js中正确封装了useDispatch(TypeScript环境需保证类型正确,JS环境可省略类型):
import { useDispatch, useSelector } from 'react-redux' import type { AppDispatch, RootState } from './index' export const useAppDispatch = () => useDispatch<AppDispatch>() export const useAppSelector = (selector) => useSelector<RootState>(selector)
额外优化:缓存Axios实例避免重复创建
当前代码每次调用useAxiosInstance都会生成新的Axios实例,存在性能浪费。可以用useMemo缓存实例,仅在依赖变化时重新创建:
import { useMemo } from 'react'; // ...其他导入 const useAxiosInstance = () => { const dispatch = useAppDispatch() const router = useRouter() const instance = useMemo(() => { const axiosInstance = axios.create({ baseURL: 'http://localhost:4000' }); axiosInstance.defaults.withCredentials = true axiosInstance.interceptors.response.use((response) => { return response }, (error) => { if(error.response?.status === 401 && window.location.href !== 'http://localhost:3000/') { router.push('/') dispatch(stopLoading()) } return Promise.reject(error) }) return axiosInstance }, [dispatch, router]) return instance } export default useAxiosInstance
内容的提问来源于stack exchange,提问作者Marcus
相关产品推荐
相关产品推荐

