0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React useContextとuseStateを使ってnumber型の配列を制御する

Last updated at Posted at 2023-02-08

概要

useContextとuseStateを使ってnumber型の配列のStateの実装方法を投稿します。

開発環境

IDE:VSCode
React:18.20

サンプル

動かしているときの様子(gifアニメ)
右側のログはStateの状態を出力しています。
context-check.gif

ボタンの名前 機能
削除 対応する子コンポーネントが削除されます。
追加 対応する子コンポーネントのcountが+1されます。
ChildCを追加 子コンポーネントを追加します。

実装

ファイルは2つ作ります。
1.Stateを管理するファイル(親コンポーネント)
2.1のStateを使うコンポーネント(子コンポーネント)

1.親コンポーネント側の設定(Providerの設定)

Providerで子コンポーネントに値を渡します。

index.tsx
import { createContext, useState } from "react";
import ChildC from "./childC";

// Contextを作成
export const UserCount = createContext();

// 親コンポーネント
export default function Index() {
  const [counts, setCounts] = useState<number[]>([1, 2]);
  console.log(counts);
  return (
    <>
      {counts.map((item: number, index: number) => {
        // useStateとindexを渡している
        // indexがないと、子コンポーネント側で自身の配列を特定できない
        const values = { counts, setCounts, index };
        return (
          // valuesの値をChildC側に渡している
          // 子コンポーネント1つにつき、別々のindexを渡すため、1つのContextを作成している。
          <UserCount.Provider value={values} key={index}>
            <ChildC />
          </UserCount.Provider>
        );
      })}
      <div></div>
    </>
  );
}

2.子コンポーネントの設定(useContextの設定)

useContextを使って、親コンポーネントのvaluesを受け取ります。

childC.tsx
import { useContext } from "react";
import { UserCount } from ".";

// 子コンポーネント
// 親からContextを受け取っている
export default function ChildC() {
  const { counts, setCounts, index } = useContext(UserCount);
  return (
    <>
      <div>番号{counts[index]}</div>
    </>
  );
}

3.ボタン類の実装(Stateの配列の処理)

以下処理を実装します。
1,2で作ったファイルにボタン押下処理を追加します。
書き方に癖があって試行錯誤しました。Stateの配列は普通のArrayのようにpop pushでやるとエラーになります。

index.tsx
import { createContext, useState } from "react";
import ChildC from "./childC";

// Contextを作成
export const UserCount = createContext();

// 親コンポーネント
export default function Index() {
  const [counts, setCounts] = useState<number[]>([1, 2]);
+  const addHandler = () => {
+    // スプレッド構文で表現
+    // count.push(1)でやるとエラーになる
+    setCounts([...counts, 1]);
+  };
  console.log(counts);
  return (
    <>
      {counts.map((item: number, index: number) => {
        // useStateとindexを渡している
        // indexがないと、子コンポーネント側で自身の配列を特定できない
        const values = { counts, setCounts, index };
        return (
          // valuesの値をChildC側に渡している
          // 別々のindexを渡すため子コンポーネント1つにつき、1つのContextを作成している。(子:Provider=1:1の割合 多:1だとNG)
          <UserCount.Provider value={values} key={index}>
            <ChildC />
          </UserCount.Provider>
        );
      })}
      <div></div>
+      <button onClick={addHandler}>ChildCを追加</button>
    </>
  );
}

childC.tsx
import { useContext } from "react";
import { UserCount } from ".";

// 子コンポーネント
// 親からContextを受け取っている
export default function ChildC() {
  const { counts, setCounts, index } = useContext(UserCount);

+  // 子コンポーネントの存在を削除する
+  const deleteHandler = () => {
+    // counts.pop(index)でやるとエラーになる
+    setCounts(counts.filter((count: number, i: number) => i !== index));
+  };
+  // count[index]を+1するボタン
+  const addHandler = () => {
+    // index番目の時だけcountを追加している
+    setCounts(
+      counts.map((count: number, i: number) =>
+        i === index ? count + 1 : count
+      )
+    );
+  };

  return (
    <>
      <div>番号{counts[index]}</div>
+      <button onClick={addHandler}>追加</button>
+      <button onClick={deleteHandler}>削除</button>
    </>
  );
}

参考資料

Contextの設定の仕方

配列のStateに追加削除する方法

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?