React Hooks(useState)のプッシュメソッド?


回答:


307

を使用useStateすると、状態アイテムの更新メソッドを取得できます。

const [theArray, setTheArray] = useState(initialArray);

次に、新しい要素を追加する場合は、その関数を使用して、新しい配列または新しい配列を作成する関数を渡します。通常は後者です。状態の更新は非同期であり、バッチ処理されることもあるためです。

setTheArray(oldArray => [...oldArray, newElement]);

次のような特定のユーザーイベントのハンドラーで配列を更新するだけの場合は、そのコールバックフォームを使用せずに逃げることができる場合がありますclick(ただし、そうではありませんmousemove)。

setTheArray([...theArray, newElement]);

Reactがレンダリングのフラッシュを保証するイベントは、ここにリストされている「離散イベント」です

実例(コールバックをに渡すsetTheArray):

theArrayそこへの唯一の更新はclickイベント内のもの(「離散」イベントの1つ)であるため、次の場所で直接更新することで回避できますaddEntry


1
...そしてsetTheArray(currentArray => [...currentArray, newElement])上記がうまくいかない場合は試してみてください。ほとんどの場合ではuseEffect(...theArray..., [])、それはそれは理解することが重要ですtheArrayので、定数、ある機能の更新が未来からの値のために必要とされるレンダリング
Aprillion

@ Aprillion-そのuseEffect例で何を言っているのかよくわかりません...?
TJクラウダー

1
useEffect空の依存関係リストがある場合、[]最初のレンダリング中にのみ実行されます。したがって、theArrayエフェクト内の値は常にになりますinitialArraysetTheArray([...initialArray, newElement])意味をなさない状況で、theArray定数が常にに等しい場合はinitialValue、機能の更新が必要です。
アプリリオン

@ Aprillion-私はまだそれを取得していないのではないかと心配しています。おそらく少し密集しています。:-)配列の初期値だけでエフェクトが必要なのはなぜですか?(つまり、使用頻度が低い場合もありますが...)そして、たとえそうだとしても、それは質問と何の関係があるのでしょうか?
TJクラウダー

1
男、私はこれに最も長い間苦労しました。私setTheArray(()=>theArray.concat(newElement))はうまくいくと思ったが、NO!コールバックへのそのパラメータは、すべての違いになります。
JeffLowery20年

51

もう少し拡張するために、ここにいくつかの一般的な例があります。で始まります:

const [theArray, setTheArray] = useState(initialArray);
const [theObject, setTheObject] = useState(initialObject);

配列の最後に要素をプッシュ

setTheArray(prevArray => [...prevArray, newValue])

オブジェクトの最後にある要素をプッシュ/更新します

setTheObject(prevState => ({ ...prevState, currentOrNewKey: newValue}));

オブジェクトの配列の最後にある要素をプッシュ/更新します

setTheArray(prevState => [...prevState, {currentOrNewKey: newValue}]);

配列のオブジェクトの最後にある要素をプッシュします

let specificArrayInObject = theObject.array.slice();
specificArrayInObject.push(newValue);
const newObj = { ...theObject, [event.target.name]: specificArrayInObject };
theObject(newObj);

ここにいくつかの実用的な例もあります。 https://codesandbox.io/s/reacthooks-push-r991u


5
すべての例をありがとう。私が問題を抱えていたのは、配列のオブジェクトの最後にあるPush要素でした。いろいろ試してみましたが、なかなかうまくいきませんでした。
sdouble

1
prevStateを使用すると、最後の呼び出しのみが配列の連結とフィルターの同時適用に適用されるという問題が修正されました。
HenriqueBruno20年

5

Reactクラスコンポーネントの「通常の」状態で行うのと同じ方法です。

例:

function App() {
  const [state, setState] = useState([]);

  return (
    <div>
      <p>You clicked {state.join(" and ")}</p>
      //destructuring
      <button onClick={() => setState([...state, "again"])}>Click me</button>
      //old way
      <button onClick={() => setState(state.concat("again"))}>Click me</button>
    </div>
  );
}

これは、onClickのでは動作しますが、SETSTATE(oldState => [pushsomething ... oldStateは、])あなたがそれを行う必要がありますどのようにある
サイラスZEI

3
// Save search term state to React Hooks with spread operator and wrapper function

// Using .concat(), no wrapper function (not recommended)
setSearches(searches.concat(query))

// Using .concat(), wrapper function (recommended)
setSearches(searches => searches.concat(query))

// Spread operator, no wrapper function (not recommended)
setSearches([...searches, query])

// Spread operator, wrapper function (recommended)
setSearches(searches => [...searches, query])

https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc


2

setTheArray([...theArray, newElement]);が最も簡単な答えですが、theArray内の項目の変更に注意してください。配列アイテムのディープクローニングを使用します。


あなたが言及するディープクローニングは、objAとして受け取ることを意味しますか?UseStateを使用して、objAをobjBと連結しますか?このリンクと同じですか?gist.githubusercontent.com/kahsing/...
Luiey

1

最も推奨される方法は、ラッパー関数とスプレッド演算子を一緒に使用することです。たとえば、nameこのように呼ばれる状態を初期化した場合、

const [names, setNames] = useState([])

このようにこの配列にプッシュできます、

setNames(names => [...names, newName])

お役に立てば幸いです。


リンクのみの回答は投稿しないでください。リンクは将来壊れている可能性があります。代わりに、その記事の記事を作成し、実際に質問に答えることを確認してください。
BlackCetha

このリンクは質問に答えることができますが、ここに答えの本質的な部分を含めて、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。-レビューから
ilke4 4420

1

カスタム状態の最後にデータの配列を追加できます。

  const [vehicleData, setVehicleData] = React.useState<any[]>([]);
  setVehicleData(old => [...old, ...newArrayData]);

たとえば、以下にaxiosの例を示します。

  useEffect(() => {
    const fetchData = async () => {
      const result = await axios(
        {
          url: `http://localhost:4000/api/vehicle?page=${page + 1}&pageSize=10`,
          method: 'get',
        }
      );
      setVehicleData(old => [...old, ...result.data.data]);
    };

    fetchData();
  }, [page]);

0

useStateのオブジェクトの配列にオブジェクトをプッシュするために上記のメソッドを試しましたが、TypeScriptを使用すると次のエラーが発生しました。

タイプ 'TxBacklog [] | undefined 'には、iterator.ts(2488)を返す' Symbol.iterator 'メソッドが必要です。

tsconfig.jsonの設定は明らかに正しかった:

{
   "compilerOptions": {
   "target": "es6",
   "lib": [
      "dom",
      "dom.iterable",
      "esnext",
      "es6",
],

この回避策は問題を解決しました(私のサンプルコード):

インターフェース:

   interface TxBacklog {
      status: string,
      txHash: string,
   }

状態変数:

    const [txBacklog, setTxBacklog] = React.useState<TxBacklog[]>();

新しいオブジェクトを配列にプッシュします。

    // Define new object to be added
    const newTx = {
       txHash: '0x368eb7269eb88ba86..',
       status: 'pending'
    };
    // Push new object into array
    (txBacklog) 
       ? setTxBacklog(prevState => [ ...prevState!, newTx ])
       : setTxBacklog([newTx]);

0

特定のインデックスの後にプッシュしたい場合は、以下のように実行できます。

   const handleAddAfterIndex = index => {
       setTheArray(oldItems => {
            const copyItems = [...oldItems];
            const finalItems = [];
            for (let i = 0; i < copyItems.length; i += 1) {
                if (i === index) {
                    finalItems.push(copyItems[i]);
                    finalItems.push(newItem);
                } else {
                    finalItems.push(copyItems[i]);
                }
            }
            return finalItems;
        });
    };
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.