The most common cause of the Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop
is incorrect state updates.
Let's look at a few possible scenarios where this error can occur.
setState causes an infinite loop
Take a look at the code listed below. Here is the typical life cycle the component goes through to generate the error.
- Component renders and executes
setMessage("Enter your message")
- setState causes the component to re-render
- When the component re-renders, it executes the setState again
As you can see, the above cycle continues. React Js detect this and issues the error message. That is an error, not a warning.
import { useState } from "react"
export const App = () => {
const [message, setMessage] = useState<string>()
//This will cause an infinite loop
setMessage("Enter your message")
return(
<>
<div>Name: <input value={message}/></div>
<div><button>Update</button></div>
</>
)
}
export default App
Solution 1
Set the default state variable value when the variable is initialized.
const [message, setMessage] = useState
Solution 2
Handle the state change inside the useEffect
hook.
useEffect(() => {
setMessage("Enter your message")
},[])
Using function calls instead of function references or functions
Event handlers should be functions or function references. If I use a function call as an event handler, React will execute that function upon the component render.
In the below example, I use setMessage("")
as an event handler. That will cause the same infinite loop.
import { useState } from "react"
export const App = () => {
const [message, setMessage] = useState("Enter your message")
return(
<>
<div>Name: <input value={message} onChange={(e) => setMessage(e.target.value)}/></div>
<div><button onClick={setMessage("")}>Reset</button></div>
</>
)
}
export default App
Solution
The solution is to pass a function to the onClick method.
onClick={() => setMessage("")}
Below is another example where I use a method call instead of a function or a function reference. Note that I do a state update within the resetMessage() function that causes the infinite loop.
import { useState } from "react"
export const App = () => {
const [message, setMessage] = useState("Enter your message")
const resetMessage = () => {
setMessage("")
}
return(
<>
<div>Name: <input value={message} onChange={(e) => setMessage(e.target.value)}/></div>
<div><button onClick={resetMessage()}>Reset</button></div>
</>
)
}
export default App
Solution
The solution is to pass a function to the onClick method. In this case, I use the function reference.
onClick={resetMessage}