React useEffect缺失props依赖警告 | Slack克隆项目登录校验问题
嘿,这个React Hook的依赖警告问题我熟!咱们一步步来解决它:
问题根源
你在useEffect里调用了props.setUser和props.clearUser这两个来自Redux的方法,但你的依赖数组里只加了history相关的项,完全没把这两个方法加进去。React的Hook规则要求,所有在useEffect回调里用到的外部变量都得放进依赖数组里,不然就会触发这个警告。
解决方案
咱们分两步来修复:
精准添加依赖,而非整个props
别直接把props塞进依赖数组(那样会因为props对象每次渲染的引用变化导致不必要的重跑),而是从props里解构出需要的setUser和clearUser,然后把这两个方法加入依赖数组。因为Redux的connect会确保这些dispatch方法的引用是稳定的,所以不用担心重复触发的问题。清理Firebase的监听(避免内存泄漏)
onAuthStateChanged会返回一个取消监听的函数,咱们得在组件卸载时调用它,不然会留下内存泄漏的隐患。
修改后的代码
import React,{useEffect} from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; import Login from './components/Auth/login' import Register from './components/Auth/register' import reportWebVitals from './reportWebVitals'; import {BrowserRouter as Router,Switch,Route,useHistory,withRouter} from 'react-router-dom' import 'semantic-ui-css/semantic.min.css' import firebase from './firebase' import { createStore } from 'redux' import { Provider,connect} from 'react-redux' import { composeWithDevTools } from 'redux-devtools-extension' import rootReducer from './reducers/index'; import * as actions from './actions/index'; import Spinner from './spinner' const store=createStore(rootReducer,composeWithDevTools()) const Root=({ isLoading, setUser, clearUser })=>{ const history=useHistory() useEffect(() => { console.log("1") // 保存监听的取消函数 const unsubscribe = firebase.auth().onAuthStateChanged(user=>{ if(user){ setUser(user); history.push('/home') } else{ history.push('/login') clearUser(); } }) // 组件卸载时取消监听 return () => unsubscribe() }, [history, setUser, clearUser]) // 这里加入需要的依赖 return isLoading ? <Spinner/>:( <Switch> <Route exact path="/home" component={App} /> <Route path="/login" component={Login} /> <Route path="/register" component={Register} /> </Switch> ) } const mapStateToProps=state=>{ return { isLoading:state.user.isLoading, user:state.user.currentuser } } const mapDispatchToProps=dispatch=>{ return{ setUser:(user)=>dispatch(actions.SETuser(user)), clearUser:()=>dispatch(actions.CLEARuser()) } } const RootwithAuth=withRouter(connect(mapStateToProps,mapDispatchToProps)(Root)) ReactDOM.render( <Provider store={store}> <Router> <RootwithAuth/> </Router> </Provider>, document.getElementById('root') ); reportWebVitals();
额外说明
- 我把
Root组件的参数改成了解构赋值,这样代码更清晰,也方便直接拿到需要的方法。 - 加入了清理函数
return () => unsubscribe(),确保组件卸载时断开Firebase的监听,避免内存泄漏。 - 依赖数组里现在包含了
history、setUser和clearUser,这三个都是useEffect回调里用到的外部变量,完全符合Hook的规则,警告也就消失啦。
内容的提问来源于stack exchange,提问作者suresh
相关产品推荐
相关产品推荐

