ReactでAPIからデータを取得して画面表示する（更新ボタンの実装）

ReactでAPIをコールしてデータを取得して画面に表示する方法はすぐに実装できました。今回は画面上に更新ボタンを設置してユーザー自身が何度でも更新できるような仕組みを作ります。

以下記事を参考にさせていただきました

https://qiita.com/Rascal823/items/0f53ffbb410505b707f8

## やりたいこと
・画面表示時にJSON文字列を返すAPIからデータを取得して一覧表示する
・ユーザーの任意のタイミングでボタン押下してAPIからデータを取得して画面を更新する
　（DOM操作ではなくReactらしく再描画で反映する）

## 構成
index.tsx　画面表示
wlist.tsx　APIからデータ取得して画面に表示する部分
hello.tsx　テスト用データを取得するAPI

### 初回表示時の実装
画面表示時にuseStateしてContext経由で使いまわします

```tsx:index.tsx
import * as React from 'react';
import Container from '@mui/material/Container';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { ButtonTest } from './button';
import { createContext, Dispatch, SetStateAction, useState } from 'react';
import axios from 'axios';
import Page from './wlist';

type User = {
  name:string,
  age:number, 
}

export const UserData = createContext({} as {
  users: User[],
  setUsers: Dispatch<SetStateAction<User[]>>
});

export default function Index() {
  const [users, setUsers] = useState<User[]>([]);
  const value = {
    users,
    setUsers,
  };
  
  function handleTestCallApi() {
      axios.get("http://localhost:3000/api/hello").then((res) => {
        res.data.forEach(element => { console.log(element)});
        setUsers(res.data);
      });
  }
  
  return (
    <Container maxWidth="sm">
      <Box sx={{ margin: 3 }}>
        <ButtonTest />
        <Button onClick={handleTestCallApi}>これです</Button>
        <UserData.Provider value={value}><Page /></UserData.Provider>
      </Box>
    </Container>
  );
}
```

### APIからデータ取得してHTMLを作る部分
index.tsxでuseStateの関数をContext経由で受け取り、取得したAPIのデータをsetUsersしています

```tsx:wlist.tsx
import axios from "axios";
import { useContext, useEffect, useState } from "react";
import { UserData } from ".";
import { ListItemValue } from "./list";

type User = {
  name:string,
  age:number, 
}
export const Page = () => {
  const {users, setUsers} = useContext(UserData);
  useEffect(() => {
    axios.get<User[]>("http://localhost:3000/api/hello").then((res) => {
      setUsers(res.data);
    })
  },[]);

  return (
    <div>
      {users.map(user => (
        <ListItemValue name={user.name} age={user.age} key={user.name}/>
      ))}
    </div>
  );
}
export default Page;
```

### (参考）テスト用API

```tsx:hello.tsx
export default function hello(req, res) {
  const items = [
    {
      "name":'ノーバット！',
      "age":10
    },
    {
      "name":'グッドワーク！',
      "age":12
    },
    {
      "name":'アプリシエイテッド',
      "age":14
    }
  ];    
  res.status(200).json(items);
}
```

### 画面の確認
画面表示時にAPIからJSON文字列を受け取り画面に表示しています。非常にわかりにくいですが「これです」というリンクをクリックすると再度APIにデータを取得しに行き、画面の一覧を更新します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110457/e21c1f9f-74a0-930c-6394-02cf24ac86ac.png)

（参考）以下はボタン押下した際に1行追加データがあった場合の更新イメージです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110457/20b45e22-05fb-c010-e375-2b5e6c31f6ee.png)


Reactを知れば知るほど多数のライブラリが存在してシンプルで自由度の高い仕組みだなと感じています。それは動きを確認しやすく楽しく学習できるが、同時に実力次第でソースの視認性／拡張性などが大きく変わるということでもあります。静的型付け／型安全などの特徴がありソースコードに一定のルール付けができるTypeScriptが人気な理由もわかりますし、業務利用できる程度の知識を身につけたい。

JSやCSSなどを個別に管理するよりReactやNext.jsで制御できたりテストコードをまとめて整備できますし、素晴らしい仕組みだなと・・・。勝手に何度も圧倒的敗北感を感じています。改めて先人の成果を利用しやすい形で安価に取り入れられるこの時代に感謝いたします。