# オブジェクトが要素の配列のstate管理

オブジェクトの要素の配列を管理することは、Webアプリにてよくあります。

`components`配下に`UserList.tsx`を作成しましょう。作成したら、以下のように`User`型を定義して、`User`型の要素を持った配列のstateを作成しましょう。

<pre class="language-tsx" data-title="UserList.tsx◎"><code class="lang-tsx"><strong>import { useState } from "react";
</strong><strong>
</strong><strong>type User = {
</strong><strong>  id: number;
</strong><strong>  name: string;
</strong><strong>  isLogin: boolean;
</strong><strong>};
</strong><strong>
</strong><strong>export const UserList = () => {
</strong><strong>  const [userList, setUserList] = useState&#x3C;User[]>([
</strong><strong>    { id: 1, name: "太郎", isLogin: false },
</strong><strong>    { id: 2, name: "次郎", isLogin: false },
</strong><strong>    { id: 3, name: "三郎", isLogin: false },
</strong><strong>  ]);
</strong><strong>};
</strong></code></pre>

そして、`userList`の1つの要素の`isLogin`を`true`にする関数を作成しましょう。

流れとしては、newUserListという定数を`...userList`と展開し、配列に再格納する形で、コピーを作成し、引数で受け取ったindex番目のisLoginをtrueに変更し(`newUserList[index].isLogin = true`)、`setUserList`に`newUserList`を格納するという形で値を更新します。

{% code title="UserList.tsx◎" %}

```tsx
...
export const UserList = () => {
  const [userList, setUserList] = useState<User[]>([
    { id: 1, name: "太郎", isLogin: false },
    { id: 2, name: "次郎", isLogin: false },
    { id: 3, name: "三郎", isLogin: false },
  ]);

  const handleLogin = (index: number) => {
    const newUserList = [...userList];
    newUserList[index].isLogin = true;
    setUserList(newUserList);
  };
};
```

{% endcode %}

returnとしては、bootstrapのテーブルを利用して、ユーザー一覧を表示します。

{% embed url="<https://getbootstrap.jp/docs/5.3/content/tables/>" %}

`userList`を`map`で回して要素を格納するのですが、`map`の第2引数にインデックスを取得することができるので、何番目の要素のbuttonが押されたかを判別することができます。そのため、`onClick`の部分を`handleLogin(index)`とします。

<pre class="language-tsx" data-title="UserList.tsx◎"><code class="lang-tsx">...
  const handleLogin = (index: number) => {
    const newUserList = [...userList];
    newUserList[index].isLogin = true;
    setUserList(newUserList);
  };

<strong>  return (
</strong><strong>    &#x3C;table className="table">
</strong><strong>      &#x3C;thead>
</strong><strong>        &#x3C;tr>
</strong><strong>          &#x3C;th scope="col">id&#x3C;/th>
</strong><strong>          &#x3C;th scope="col">名前&#x3C;/th>
</strong><strong>          &#x3C;th scope="col">ログイン状態&#x3C;/th>
</strong><strong>          &#x3C;th scope="col">&#x3C;/th>
</strong><strong>        &#x3C;/tr>
</strong><strong>      &#x3C;/thead>
</strong><strong>      &#x3C;tbody>
</strong><strong>        {userList.map((user, index) => (
</strong><strong>          &#x3C;tr key={user.id}>
</strong><strong>            &#x3C;th scope="row">{user.id}&#x3C;/th>
</strong><strong>            &#x3C;td>{user.name}&#x3C;/td>
</strong><strong>            &#x3C;td>{user.isLogin ? "ログイン中" : "未ログイン"}&#x3C;/td>
</strong><strong>            &#x3C;td>
</strong><strong>              &#x3C;button
</strong><strong>                className="btn btn-primary"
</strong><strong>                onClick={() => handleLogin(index)}
</strong><strong>              >
</strong><strong>                ログイン
</strong><strong>              &#x3C;/button>
</strong><strong>            &#x3C;/td>
</strong><strong>          &#x3C;/tr>
</strong><strong>        ))}
</strong><strong>      &#x3C;/tbody>
</strong><strong>    &#x3C;/table>
</strong><strong>  );
</strong>};
</code></pre>

では、こちらを`App.ts`にて呼び出しましょう。

<pre class="language-tsx" data-title="App.tsx"><code class="lang-tsx">...
import { Like } from "./components/Likes";
<strong>import { UserList } from "./components/UserList"; 
</strong>...
        &#x3C;Like />
      &#x3C;/div>
<strong>      &#x3C;UserList />
</strong>...
</code></pre>

上記にて、以下のようにログインボタンを押したもののみ、ログイン中と表示されるようになります。

<figure><img src="https://1869761657-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcUBbYqol4PMzZJggiMqV%2Fuploads%2FwK3zTl1hKAYDmaggGFTm%2F202312071632.png?alt=media&#x26;token=08567c53-ef61-4cf2-ac9a-2bd71ce62eb8" alt=""><figcaption></figcaption></figure>
