luckydev
luckydev

Reputation: 149

How to fix infinite re-render?

Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

Found the answers to my question, but, nevertheless, I can’t understand how to fix this?

const { useState } = React,
      { render } = ReactDOM

function App() {
  const [visible, setVisible] = useState(false);
  const [visible2, setVisible2] = useState(false);

  const arr1 = {
    company: [
      {
        id: "random1",
        companyName: "Apple"
      },
      {
        id: "random2",
        companyName: "Samsung"
      }
    ]
  };

  const onDataHandle = () => {
    return arr1.company.map(items => {
      return (
        <div>
          <span key={items.id}>
            {items.companyName}
            <span onClick={onHandleVisible}>Details</span>
          </span>
          <br />
        </div>
      );
    });
  };

  const onHandleVisible = () => {
    setVisible(!visible);
  };

  const onHandleVisible2 = () => {
    setVisible2(!visible2);
  };

  return (
    <div className="App">
      <button onClick={onHandleVisible2}>Show</button>
      {visible && onDataHandle()}
    </div>
  );
}

render (
  <App />,
  document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

I understand that this is due to the endless re-rendering, but what are the solutions?

Upvotes: 1

Views: 397

Answers (1)

Yevhen Horbunkov
Yevhen Horbunkov

Reputation: 15550

You have multiple problems in your code logic (that is not entirely clear, I must say):

  • Show button onClick triggeres onHandleVisible2 callback which sets visible2 state variable to true, but there's nothing in your code depending on that state variable, so nothing happens
  • The block {visible && onDataHandle()} is supposed to trigger onDataHandle() (which never happens for above reason - visible stays equal to false), but onDataHandle() (even though attempts to return some JSX) will not add anything to render within <App /> as it is not a ReactJS component
  • (the minor one) if your intention with onDatahandle() was to return some component, wrapping up your span with extra <div> doesn't make much sense.

With all the above issues fixed, you would get something, like:

const { useState } = React,
      { render } = ReactDOM

function App() {
  const [visible, setVisible] = useState(false);
  const [visible2, setVisible2] = useState(false);

  const arr1 = {
    company: [
      {
        id: "random1",
        companyName: "Apple"
      },
      {
        id: "random2",
        companyName: "Samsung"
      }
    ]
  };

  const Data = () => (
    <div>
      {
        arr1.company.map(items => (
          <span key={items.id}>
            {items.companyName}
            <span onClick={onHandleVisible}>Details</span>
            {visible && <span>There go {items.companyName} details</span>}
            <br />
          </span>))
       }
    </div>
  )

  const onHandleVisible = () => {
    setVisible(!visible);
  };

  const onHandleVisible2 = () => {
    setVisible2(!visible2);
  };

  return (
    <div className="App">
      <button onClick={onHandleVisible2}>Show</button>
      {visible2 && <Data />}
    </div>
  );
}

render (
  <App />,
  document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

Note one important issue stays unsolved in above code block: you used single variable (visible) for your entire app, so if you decide to control visibility of details for each item independently, you won't be able to do that with your current approach. But that's a totally different issue which you may post as a separate question.

Upvotes: 3

Related Questions