web-dev-qa-db-ja.com

反応フックuseState配列

ここでuseState配列値をリセットしようとしましたが、配列値への参照が見つかりませんでした。

ドロップダウン値を初期状態からallowedState値に変更しようとしています。ここでフックメソッドを使用して、setStateValuesを使用して値を設定しています。そのコード行をコメントすると、ドロップダウンが表示されます。 setStateValuesメソッドを使用して状態変数値をリセットできない理由を理解できませんでした。

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

ここで何かおかしいことがあったら助けてください。私は探し続けます。

    import React, { useState } from "react"; 
    import ReactDOM from "react-dom";

    const StateSelector = () => {   
    const initialValue = [
    { id: 0,value: " --- Select a State ---" }];

      const allowedState = [
        { id: 1, value: "Alabama" },
        { id: 2, value: "Georgia" },
        { id: 3, value: "Tennessee" }
        ];

      const [stateOptions, setStateValues] = useState(initialValue);  
      // initialValue.Push(...allowedState);

      console.log(initialValue.length);

      setStateValues(allowedState); // Not sure why cannot I reset the state in here for an array.

         return (<div>
          <label>Select a State:</label>
          <select>
            {stateOptions.map((localState, index) => (
              <option key={localState.id}>{localState.value}</option>
            ))}
          </select>
        </div>   ); };

    const rootElement = document.getElementById("root");
    ReactDOM.render(<StateSelector />, rootElement);
8
shavi

レンダリング関数内から状態を設定しないでください(または副作用で他のことを実行しないでください)。フックを使用する場合、useEffectを使用できます。

次のバージョンが機能します。

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const StateSelector = () => {
  const initialValue = [
    { id: 0, value: " --- Select a State ---" }];

  const allowedState = [
    { id: 1, value: "Alabama" },
    { id: 2, value: "Georgia" },
    { id: 3, value: "Tennessee" }
  ];

  const [stateOptions, setStateValues] = useState(initialValue);
  // initialValue.Push(...allowedState);

  console.log(initialValue.length);
  // ****** BEGINNING OF CHANGE ******
  useEffect(() => {
    // Should not ever set state during rendering, so do this in useEffect instead.
    setStateValues(allowedState);
  }, []);
  // ****** END OF CHANGE ******

  return (<div>
    <label>Select a State:</label>
    <select>
      {stateOptions.map((localState, index) => (
        <option key={localState.id}>{localState.value}</option>
      ))}
    </select>
  </div>);
};

const rootElement = document.getElementById("root");
ReactDOM.render(<StateSelector />, rootElement);

および ここではコードサンドボックスにあります

最終的に何らかの動的ソースから状態のリストをロードすることを想定しています(そうでなければ、allowedStateをまったく使用せずにuseStateを直接使用できます)。その場合、リストをロードするためのそのAPI呼び出しは、useEffectブロック内に入れることもできます。

10
Ryan Cogswell

ライアンの答えを拡大するには:

SetStateValuesが呼び出されるたびに、React=はコンポーネントを再レンダリングします。つまり、StateSelectorコンポーネント関数の関数本体が再実行されます。

React docs

shouldStateUpdate()がfalseを返さない限り、setState()は常に再レンダリングを行います。

基本的に、次の状態を設定しています。

setStateValues(allowedState);

再レンダリングを実行すると、関数が実行されます。したがって、ループの問題。

ポイントを説明するために、タイムアウトを次のように設定した場合:

  setTimeout(
    () => setStateValues(allowedState),
    1000
  )

「再レンダリングが多すぎる」という問題はこれで終わりです。

あなたの場合、あなたはコンポーネント関数のUseEffectで処理される副作用を扱っています。詳細については、こちらをご覧ください こちら

2
Joel H

状態を最小限に抑えるようにしてください。保管する必要はありません

   const initialValue = [
    { id: 0,value: " --- Select a State ---" }];

状態として。パーマネントを変化から分離する

const ALL_STATE_VALS = [
    { id: 0,value: " --- Select a State ---" }
    { id: 1, value: "Alabama" },
    { id: 2, value: "Georgia" },
    { id: 3, value: "Tennessee" }
];

次に、状態としてidのみを保存できます。

const StateSelector = () =>{
  const [selectedStateOption, setselectedStateOption] = useState(0);

  return (
    <div>
      <label>Select a State:</label>
      <select>
        {ALL_STATE_VALS.map((option, index) => (
          <option key={option.id} selected={index===selectedStateOption}>{option.value}</option>
        ))}
      </select>
    </div>);
   )
}
1
Ben Carp

受け入れられた答えは、setStateの正しい方法を示していますが、選択ボックスが適切に機能していません。

import React, { useState } from "react"; 
import ReactDOM from "react-dom";

const initialValue = { id: 0,value: " --- Select a State ---" };

const options = [
    { id: 1, value: "Alabama" },
    { id: 2, value: "Georgia" },
    { id: 3, value: "Tennessee" }
];

const StateSelector = () => {   
   const [ selected, setSelected ] = useState(initialValue);  

     return (
       <div>
          <label>Select a State:</label>
          <select value={selected}>
            {selected === initialValue && 
                <option disabled value={initialValue}>{initialValue.value}</option>}
            {options.map((localState, index) => (
               <option key={localState.id} value={localState}>
                   {localState.value}
               </option>
             ))}
          </select>
        </div>
      ); 
};

const rootElement = document.getElementById("root");
ReactDOM.render(<StateSelector />, rootElement);
0
Avin Kavish