web-dev-qa-db-ja.com

「エラー:再レンダリングが多すぎます。Reactは、無限ループを防ぐためにレンダリングの数を制限します。」

こんにちはReact関数useStateで立ち往生しています。フックとuseStateを学びたいだけですが、解決策を見つけるのにあまりにも苦労していても進歩はありません。これが私の完全な反応関数です:

import React, { useState } from 'react';
import './MainPart.css';

function MainPart(props) {
  const [orderData_, setOrderData_] = useState(props.orderData);

  let topicData_ = props.topicData;
  let titleData_ = props.titleData;
  let infoData_ = props.infoData;

  return (
    <div className='MainPart'>
      <div className='mainWindow'>{getPics(orderData_)}</div>
      <div className='information'>
        <div className='moreNewsDivs'>
          <div className='moreNewsDiv1'>
            <h4>MORE NEWS</h4>
          </div>
          <div className='moreNewsDiv2'>
            <button
              className='previous-round'
              onClick={setOrderData_(previous(orderData_))}
            >
              &#8249;
            </button>
            &nbsp;&nbsp; &nbsp;&nbsp;
            <button href='/#' className='next-round'>
              &#8250;
            </button>
          </div>
        </div>
        <hr />
        <div className='topicDiv'>
          <h5 className='topicData'>{topicData_}</h5>
          <h5 className='titleData'>{titleData_}</h5>
          <h6 className='infoData'>{infoData_}</h6>
        </div>
      </div>
    </div>
  );
}

function previous(orderData_) {
  let newOrderData;

  if (orderData_ === 3) {
    newOrderData = 2;
    console.log(newOrderData);
    return newOrderData;
  } else if (orderData_ === 1) {
    newOrderData = 3;
    console.log(newOrderData);
    return newOrderData;
  } else {
    newOrderData = 1;
    console.log(newOrderData);
    return newOrderData;
  }
}

function next(orderData_) {
  let newOrderData;

  if (orderData_ === 3) {
    newOrderData = 1;
  } else if (orderData_ === 2) {
    newOrderData = 3;
  } else {
    newOrderData = 2;
  }
  return newOrderData;
}

const getPics = picOrder => {
  if (picOrder === 1) {
    return (
      <img
        src={require('../assets/desktopLarge/mainImage.png')}
        className='MainImage'
        alt=''
        id='mainImage'
      />
    );
  } else if (picOrder === 2) {
    return (
      <img
        src={require('../assets/desktopLarge/bridge.png')}
        className='MainImage'
        alt=''
        id='mainImage'
      />
    );
  } else {
    return (
      <img
        src={require('../assets/desktopLarge/forest.png')}
        className='MainImage'
        alt=''
        id='mainImage'
      />
    );
  }
};

export default MainPart;

useStateの使用中にエラーが発生します。新しいページをロードし、何も押されていない状態でも、ボタンのonClickイベントリスナーがアクティブ化され、トピック「エラー」で前述したように:

「エラー:再レンダリングが多すぎます。Reactは、無限ループを防ぐためにレンダリングの数を制限します。」

2
Serkan AKMAN

問題はonClickプロップにあります:

<button className="previous-round" onClick={setOrderData_(previous(orderData_))}>&#8249;</button>

中括弧の間はすべてすぐに評価されます。これにより、setOrderData_すべてのレンダーループで呼び出される関数。

関数をアロー関数でラップすることにより、評価されたコードは、ユーザーがボタンをクリックするたびに呼び出すことができる関数になります。

JSXと式の詳細については、公式ドキュメント https://reactjs.org/docs/introducing-jsx.html#embedding-expressions-in-jsx をご覧ください。

<button className="previous-round" onClick={() => setOrderData_(previous(orderData_))}>&#8249;</button>
8
Christiaan

コードを調べたところ、何かが見つかりました。

Onclick関数は矢印関数である必要があります。 Onclickはイベントであり、onclick内の関数を直接呼び出すだけです。これは、リターン内で直接状態を設定しているため、再レンダリングが多すぎます。それは機能しません。

ここでsetStateを呼び出すと、コンポーネントが無限ループを生成する可能性があります。 renderは純粋なままで、状態またはプロップに基づいてJSXフラグメント/子コンポーネントを条件付きで切り替えるために使用する必要があります。レンダリングのコールバックを使用して、状態を更新してから、変更に基づいて再レンダリングできます。ここのリンクから取得したこの上記の行: https://itnext.io/react-setstate-usage-and-gotchas-ac10b4e03d6

3

ボタンを下のボタンに置​​き換えるだけです

<button className="previous-round" onClick={() => setOrderData_(previous(orderData_))}>&#8249;</button>

これは、無名関数なしでonClick関数を使用すると即座に呼び出され、そのsetOrderDataが再度レンダリングされるために無限ループが発生するために発生します。したがって、無名関数を使用する方が良いでしょう。

それが役に立てば幸い。疑いはお気軽に。

3
Gaurav Roy