原文:3 ways to cause an infinite loop in React
https://alexsidorenko.com/blog/react-infinite-loop/
React 中 3 种导致无限循环的方式
July 05, 2021
你有没有花时间尝试调试一个React 里的无限循环? 也许在这个过程中浏览器挂了几次,或者你遇到过如下的错误信息👇
Uncaught Error: Too many re-renders.
React limits the number of renders
to prevent an infinite loop.
以下是 React 中无限循环的 3 个潜在原因。
I. Updating the state inside the render
function App() {
const [count, setCount] = useState(0);
setCount(1); // infinite loop
return ...
}
如果你直接在render方法或函数式组件的主体内更新状态,就会导致无限循环。
State updates → triggers re-render → state updates → triggers re-render → …
修正 🎉
你只想在组件挂载(mount)时更新一次状态吗? 使用以空数组作为依赖项的useEffect.
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(1);
}, [])
return ...
}
II. useEffect 里的无限循环
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1) // infinite loop
}, [count])
return ...
}
如果你在 useEffect 内不断更新状态,并设置被更新的属性为 useEffect 的依赖项,将导致无限循环。
count updates → useEffect detects updated dependency → count updates → useEffect detects updated dependency → …
修正 🎉
如果要根据之前的值更新状态,请使用函数式更新。 这样,你可以从依赖列表中删除 state 属性从而避免无限循环。
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(previousCount => previousCount + 1)
}, [])
return ...
}
III. 不正确地设置 event handler
export default function App() {
const [count, setCount] = useState(0);
return (
<button onClick={setCount(1)}>Submit</button> // infinite loop
);
}
这不是设置 event handler 的正确方法,你需要向 onClick 提供一个函数,而非函数执行的结果。 通过在设置 event handler 之前就执行函数,render 内部的状态将被更新,这会导致无限循环。
State updates → triggers re-render → state updates → triggers re-render → …
修正 🎉
为 onClick 事件设置一个函数, 这是设置 event handler 的正确方法。 这样,状态只会在单击按钮后更新,不会导致无限循环。
export default function App() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(1)}>Submit</button> // infinite loop
);
}
如何发现无限循环
每次更新状态时,请想象更新后将发生的事件序列。 如果没有额外的用户交互,这个事件序列会导致你回到相同的状态更新,你可能有一个无限循环。
本文介绍了在React中导致无限循环的三种常见方式:在render方法内更新状态、在useEffect中循环更新状态及不当配置事件处理器。同时提供了相应的解决办法。
1027





