React+Supabase项目useContext调用setCurrentUser报错:不是函数
问题描述
在React+Supabase项目中,尝试通过useContext全局存储当前用户信息,实现点击图标时判断显示个人资料或登录提示。目前在App.js中调用setCurrentUser时,控制台持续报错“setCurrentUser isn't a function”,应用虽能运行但错误无法消除。此前未调用setCurrentUser时,能正常打印用户数据。
问题原因
- Context解构错误:App.js中直接将
useContext(DataContext)赋值给setCurrentUser,但DataContext提供的是包含currentUser和setCurrentUser的对象,而非单独的setCurrentUser函数,导致setCurrentUser实际是个对象,调用时自然报错。 - useEffect无限循环:
useEffect未设置依赖数组,会在组件每次渲染时重复执行,频繁调用Supabase接口并尝试更新状态。
修复方案
步骤1:正确解构Context对象
在App.js中,通过对象解构从Context中获取setCurrentUser:
const { setCurrentUser } = useContext(DataContext)
步骤2:添加useEffect依赖数组
给useEffect添加空依赖数组,确保仅在组件挂载时执行一次:
useEffect(() => { async function fetchData() { const { data: { user } } = await backbase.auth.getUser() setCurrentUser(user) } fetchData() }, []) // 空数组确保只执行一次
修改后的完整App.js代码
import Navbar from './components/Navbar'; import Footer from './components/Footer'; import Home from './components/Home'; import AboutUs from './components/AboutUs'; import Contact from './components/Contact'; import AuthPage from './components/AuthPage'; import Products from './components/Products'; import Pants from './components/Pants'; import Missing from './components/Missing'; import { Route, Routes as Switch } from 'react-router-dom'; import React, { useEffect, useContext } from 'react'; import DataContext from './components/context/DataContext'; import backbase from './config/backbaseClient'; function App() { // 正确解构Context中的setCurrentUser const { setCurrentUser } = useContext(DataContext) useEffect(() => { async function fetchData() { const { data: { user } } = await backbase.auth.getUser() setCurrentUser(user) } fetchData() }, [setCurrentUser]) // 添加依赖,避免lint警告 return ( <div className="App"> <Navbar /> <Switch> <Route path="/home" element={<Home />} /> <Route path="/contact" element={<Contact />} /> <Route path="/about_us" element={<AboutUs />} /> <Route path="/user" element={<AuthPage />} /> <Route path="/products" element={<Products />} /> <Route path='/pants' element={<Pants />} /> <Route path="*" element={<Missing />} /> </Switch> <Footer /> </div> ); } export default App;
可选优化:封装状态更新函数
按照你在DataContext注释里的建议,可以封装一个专门的更新函数,避免直接暴露setCurrentUser:
// DataContext.js修改部分 export const DataProvider = ({ children }) => { const [currentUser, setCurrentUser] = useState(null) const updateCurrentUser = (user) => { setCurrentUser(user) } return ( <DataContext.Provider value={{ currentUser, updateCurrentUser }}> {children} </DataContext.Provider> ) }
之后在App.js中解构updateCurrentUser并调用即可。
内容的提问来源于stack exchange,提问作者StackerCen
相关产品推荐
相关产品推荐

