如何解决React函数组件Too many re-renders无限重渲染错误?
解决React函数组件无限重渲染的问题
嘿,我一眼就揪出问题所在啦!你在组件的顶层直接写了setLoading(false);——这就是触发无限循环的罪魁祸首。
为什么会出现无限重渲染?
React函数组件每次渲染时,都会从头到尾执行整个函数体的代码。你把setLoading(false);直接放在函数顶层,意味着每次组件渲染都会调用这个状态更新函数,而状态更新又会触发组件重新渲染,这样就形成了「渲染→更新状态→再渲染→再更新状态」的死循环,React为了保护应用不崩溃,就抛出了「Too many re-renders」的错误。
修复步骤
那行单独的setLoading(false);本来应该是clearUsers函数的一部分,你不小心把它写到函数外面了。只需要把它移进clearUsers的函数体内就行:
原来的错误代码:
// Clear users from state const clearUsers = () => setUsers([]); setLoading(false);
修正后:
// Clear users from state const clearUsers = () => { setUsers([]); setLoading(false); };
修正后的完整代码
import React, {Fragment, useState} from 'react'; import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import Navbar from './Components/Layout/Navbar'; import Users from './Components/users/Users'; import User from './Components/users/User'; import Search from './Components/users/Search'; import Alert from './Components/Layout/Alert'; import About from './Components/pages/About'; import './App.css'; import Axios from 'axios'; const App = () => { const [users, setUsers] = useState( [] ); const [user, setUser] = useState( {} ); const [repos, setRepos] = useState( [] ); const [loading, setLoading] = useState( false ); const [alert, setAlert] = useState( null ); // Search Github Users const searchUsers = async text => { setLoading(true); const res = await Axios.get(`https://api.github.com/search/users?q=${text}&client_id=${process.env.REACT_APP_GITHUB_CLIENT_ID}&client_secret=${process.env.REACT_APP_GITHUB_CLIENT_SECRET}`); setUsers(res.data.items); setLoading(false); }; // Get single github user const getUser = async username => { setLoading(true); const res = await Axios.get(`https://api.github.com/users/${username}?&client_id=${process.env.REACT_APP_GITHUB_CLIENT_ID}&client_secret=${process.env.REACT_APP_GITHUB_CLIENT_SECRET}`); setUser(res.data); setLoading(false); }; // Get users repos const getUserRepos = async username => { setLoading(true); const res = await Axios.get(`https://api.github.com/users/${username}/repos?per_page=5&sort=created:asc&client_id=${process.env.REACT_APP_GITHUB_CLIENT_ID}&client_secret=${process.env.REACT_APP_GITHUB_CLIENT_SECRET}`); setRepos(res.data); setLoading(false); }; // Clear users from state const clearUsers = () => { setUsers([]); setLoading(false); }; // Set Alert const showAlert = (msg, type) => { setAlert({msg, type}); setTimeout(()=> setAlert(null),3000); }; return ( <Router> <div className="App"> <Navbar /> <div className="container"> <Alert alert={alert} /> <Switch> <Route exact path='/' render={props => ( <Fragment> <Search searchUsers={searchUsers} clearUsers={clearUsers} showClear={ users.length>0? true : false } setAlert={showAlert} /> <Users loading={loading} users={users} /> </Fragment> )} /> <Route exact path = '/about' component={About} /> <Route exact path= '/user/:login' render={props => ( <User {...props} getUser={getUser} getUserRepos={getUserRepos} user={user} repos={repos} loading={loading} /> )} /> </Switch> </div> </div> </Router> ); } export default App;
额外小提醒
以后写函数组件时要记住:状态更新函数(比如setXxx)不要直接放在组件顶层执行,除非你用useEffect加了合适的依赖项来控制执行时机。所有状态更新都应该放在事件处理函数、异步回调或者useEffect里面,这样才能避免不必要的重渲染。
内容的提问来源于stack exchange,提问作者pukar upreti
相关产品推荐
相关产品推荐

