Reputation: 385
When i use useState
it shows in the console 2 renders, and if i call setVal
it throws the error Too many re-renders. React limits the number of renders to prevent an infinite loop.
. Why?
import React from "react";
export default function Home() {
console.log("render");
const [val, setVal] = React.useState();
// setVal(1);
return <div></div>;
}
I think it should be only 1 render, and only 2 renders if i call setVal()
, right?
Upvotes: 1
Views: 77
Reputation: 3176
IF you used create-react-app to startup your application, you must have <React.StrictMode>
wrapper in your index.js file:
<React.StrictMode>
<App />
</React.StrictMode>
The reason why this happens is an intentional feature of the React.StrictMode.
Remove that wrapper and it should fix it.
Upvotes: 1
Reputation: 12919
Here is a snippet illustrating three basic ways of setting and handling state with useState
.
val1
is set to 1 by providing an initial value to useState
and doesn't change.
val2
is not initially set, but useEffect
is called after the initial render and sets it's value to set with useEffect
. We have provided an empty dependency array to useEffect
so it will only run once.
val3
is initialized in the same way as val1
and it's value is changed via the handleClick
function.
As to your question about the number of renders, useState
looks for changes of state and calls renders accordingly. By calling setState
the way you are you are changing the state on each render and thus triggering a new render...ad infinitum. It should be noted that this is not a one to one process. The docs walk you through it pretty clearly.
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<div id="App"></div>
<script type="text/babel">
const { useState, useEffect} = React;
function Home() {
console.log("render");
const [val1, setVal1] = React.useState(1);
const [val2, setVal2] = React.useState();
const [val3, setVal3] = React.useState('Click me');
useEffect(()=>{
setVal2('set with useEffect');
},[])
const handleClick = () => {
setVal3('set with handler');
}
return (
<div>
<p>{val1}</p>
<p>{val2}</p>
<button type="button" onClick={handleClick}>{val3}</button>
</div>
);
}
ReactDOM.render(<Home />, document.getElementById('App'));
</script>
Upvotes: 0