mario
mario

Reputation: 385

React useState re-rendering

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?

https://codesandbox.io/s/focused-black-j1zow?fontsize=14&hidenavigation=1&theme=dark&file=/src/App.js

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

Answers (2)

Karan Kumar
Karan Kumar

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

pilchard
pilchard

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

Related Questions