產生"Too many re-renders. React limits the number of renders to prevent an infinite loop"錯誤有多方面的原因:
useEffect
勾點。這裡有個範例來展示錯誤是如何發生的:
import {useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(0);
// ⛔️ Too many re-renders. React limits the number
// of renders to prevent an infinite loop.
return (
<div>
<button onClick={setCounter(counter + 1)}>Increment</button>
<h1>Count: {counter}</h1>
</div>
);
}
上述程式碼問題在於,我們在onClick
事件處理器中立即呼叫了setCounter
函數。
該函數是在頁面載入時立即被呼叫,而不是事件觸發後呼叫。
為了解決該錯誤,為onClick
事件處理器傳遞函數,而不是傳遞呼叫函數的結果。
import {useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(0);
return (
<div>
<button onClick={() => setCounter(counter + 1)}>Increment</button>
<h1>Count: {counter}</h1>
</div>
);
}
現在,我們為事件處理器傳遞了函數,而不是當頁面載入時呼叫setCounter
方法。
如果該方法在頁面載入時被呼叫,就會觸發一個
setState
動作,元件就會無限重新渲染。
如果我們試圖立即設定一個元件的狀態,而不使用一個條件或事件處理器,也會發生這個錯誤。
import {useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(0);
// ⛔️ Too many re-renders. React limits the number
// of renders to prevent an infinite loop.
setCounter(counter + 1);
return (
<div>
<h1>Count: {counter}</h1>
</div>
);
}
問題在於,setCounter
函數在元件渲染時被呼叫、更新狀態,並導致重新渲染,而且是無限重新渲染。
你可以通過向useState()
勾點傳遞一個初始值或一個函數來初始化狀態,從而解決這個錯誤。
import {useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(() => 100 + 100);
return (
<div>
<h1>Count: {counter}</h1>
</div>
);
}
我們向useState
方法傳遞了一個函數。這個函數只會在元件第一次渲染時被呼叫,並且會計算出初始狀態。你也可以直接向useState
方法傳遞一個初始值。
另外,你也可以像前面的例子那樣使用一個條件或事件處理器。
import {useState} from 'react';
export default function App() {
const [counter, setCounter] = useState(0);
//