React+Express认证系统中fetchUser Action重复调用问题求助
React+Express认证系统:fetchUser Action被调用两次的问题
我基于React和Express开发认证系统时遇到问题:Redux DevTools显示fetchUser action被调用了两次。已经尝试移除useEffect的所有依赖,但问题依然存在。相关代码如下:
App组件
function App() { const [isAuth,setisAuth]=useState(false) const [isLoading,setIsLoading]=useState(true) const dispatch=useDispatch() useEffect(()=>{ const token=localStorage.getItem('token') console.log("Dans useEffect") async function getUser(){ try { await dispatch(fetchUser()) setisAuth(true) setIsLoading(false) } catch (error) { console.log(error) return } } token? getUser():setIsLoading(false) },[dispatch]) function Relog(arg){ setisAuth(arg) } if(isLoading){ return <div className="container d-flex justify-content-center align-items-center" style={{height:'90vh'}}> {console.log('Je suis dans mon rendu loading')} <Loading/> </div> } return ( <authContext.Provider value={{isAuth,Relog}}> {console.log('Je suis dans mon rendu App')} <Router > <Header/> <Switch> <Route exact path='/' component={MovieList}/> <Route exact path='/movie/:movieId' component={MovieDetail}/> <PrivateRoute exact path='/favoris' component={FavoriteList}/> <Route exact path='/search' component={SearchResult}/> <Route exact path='/signin' component={Auth}/> <Route exact path='/test' component={Test}/> <Route component={PageNotFound}/> </Switch> </Router> </authContext.Provider> ); } export default App;
fetchUser Action
export function fetchUser(){ console.log('Fectch user action') return async(dispatch)=>{ try { const res=await fetch(`http://127.0.0.1:5000/api/auth/verify`,{ headers:{ 'Authorization':`Bearer ${localStorage.getItem('token')}` }, method:'get' }) const data=await res.json() if(data.error) throw data.error dispatch({type:FETCH_USER,payload:data.user}) } catch (error) { throw error } } }
验证Token接口
router.get('/verify',auth,(req,res)=>{ return res.status(200).json({user:req.user}) })
认证中间件
module.exports = async(req, res, next) => { try { const header=req.headers.authorization; if(!header) return res.status(401).json({error:{message:"Erreur d'authentification,Veuillez vous connecter"}}) const token = header.split(' ')[1]; const decodedToken = jwt.verify(token, process.env.SECRET); const user=await User.findByPk(decodedToken.userId) if(!user) throw new Err('Erreur d\'authentification',404) if(user.blocked) throw new Err('Votre compte est inactif pour le moment',404) req.user=user req.auth = {...decodedToken}; next(); } catch(error) { if(error instanceof jwt.JsonWebTokenError) return res.status(401).json({error:{message:error.message}}); next(error) } };
问题排查与解决方案
1. React Strict Mode 双重渲染(最常见原因)
开发环境下,React的<StrictMode>会刻意重复调用useEffect、组件函数等,目的是检测潜在的副作用问题。这会导致你的useEffect执行两次,进而触发两次fetchUser。
- 验证方式:检查项目入口文件(通常是
index.js),看是否用<React.StrictMode>包裹了<App />。 - 处理方案:
- 生产环境下该问题会自动消失,无需额外处理;
- 若要在开发环境临时避免,可移除
<StrictMode>包裹,但不推荐——Strict Mode能帮你提前发现很多隐蔽的bug。
2. 标记执行状态,避免重复调用
如果需要确保fetchUser只执行一次,可通过useRef标记是否已经完成初始化:
useEffect(()=>{ const token=localStorage.getItem('token') const hasFetched = useRef(false); async function getUser(){ if(hasFetched.current) return; hasFetched.current = true; try { await dispatch(fetchUser()) setisAuth(true) setIsLoading(false) } catch (error) { console.log(error) setIsLoading(false) return } } token? getUser():setIsLoading(false) },[dispatch])
3. 检查是否有其他触发源
排查其他组件或action中是否也调用了fetchUser,比如Header组件或者PrivateRoute的权限校验逻辑,是否存在重复触发的情况。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

