原文: How to Perform CRUD Operations using React, React Hooks, and Axios

React を扱っていれば、API リクエストを理解し実装するのはとても難しいと感じられるでしょう。

そこでこの記事では、React 、React Hooks、React Router、Axios を用いて CRUD 操作を実装することにより、そのすべてがどのように機能するかを学んでいきます。

さあはじめましょう。

Node と npm をインストールする方法

まず最初に、Node をシステム内にインストールしましょう。私たちは主にそれを用いて JavaScript のコードを実行します。

Node をダウンロードするには、https://nodejs.org/en/ にアクセスしてください。

Node上に構築された Node パッケージマネージャー (npm) も必要です。それを用いることで、JavaScript アプリ用のパッケージをインストールできます。幸い、npm は Node に備わっているため、個別にダウンロードする必要はありません。

両方のダウンロードが終了したら、ターミナルかコマンドプロンプトを開いて、node -v と入力してみましょう。これでダウンロードした Node のバージョンを確認します。

React アプリケーションを作成する方法

次に、React アプリケーションを作成するには、ターミナル内で npx create-react-app <Your app name> と入力しますが、今回は npx create-react-app react-crud と入力します。

そうすると、パッケージのインストール状態が表示されます。

パッケージのインストールが終わったら、プロジェクトフォルダーへ移動して、npm start と入力します。

すると、次のような初期状態の React テンプレートが表示されます:

Screenshot-2021-07-24-124754
初期状態の React テンプレート
Screenshot-2021-07-24-124858
App.js ファイル

React 用の Semantic UI パッケージをインストールする方法

次に、Semantic UI React パッケージをインストールしましょう。Semantic UI は、React 用に作られた UI (ユーザーインターフェース) ライブラリーです。Semantic UI には、テーブル、ボタンなどの機能をもつ多くの UI コンポーネントが、あらかじめ構築されています。

以下のコマンドを、ご自身のパッケージマネージャーに応じて入力すれば、Semantic UI をインストールできます。

yarn add semantic-ui-react semantic-ui-css
Yarn パッケージマネージャー用のコマンド
npm install semantic-ui-react semantic-ui-css
NPM パッケージマネージャー用のコマンド

また、アプリケーションのメインエントリーファイルである index.js に、インストールしたライブラリーをインポートします。

import 'semantic-ui-css/semantic.min.css'
こちらを index.js ファイル内へ貼り付けてください

CRUD アプリケーションを構築する方法

では、React を用いて CRUD アプリケーションの構築を始めましょう。

最初に、アプリケーションにヘッダーを追加しましょう。

以下のようにして、App.js ファイル内にヘッダーを追加します:

import './App.css';

function App() {
  return (
    <div>
      React Crud Operations
    </div>
  );
}

export default App;
アプリケーションにヘッダーを追加

次に、ヘッダーを中央に配置しましょう。

親要素 div の、className 属性の値を main に設定してください。それから、App.css ファイル内でフレックスボックスを使用して、ヘッダーを中央に配置しましょう。

import './App.css';

function App() {
  return (
    <div className="main">
      React Crud Operations
    </div>
  );
}

export default App;
App.js の中で 親要素 div の className 属性の値を main に設定
.main{
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #212121;
  color: whitesmoke;
}
App.css ファイル
Screenshot-2021-07-24-130340

これでヘッダーは完全に中央に配置されました。

見た目が少し良くなるように、ヘッダーをより目立たせて、かっこいいフォントを設定する必要があります。そのために、まずは以下のようにして見出しタグをヘッダーの周りに追加します:

import './App.css';

function App() {
  return (
    <div className="main">
      <h2>React Crud Operations</h2>
    </div>
  );
}

export default App;

次に Google Fonts からフォントをインポートしましょう。 https://fonts.google.com/ にアクセスし、1 つ選択します。

お好みのフォントを選択してください。ただし、この記事の中では Montserrat フォントファミリーを使用します。

フォントを選択したら、次のようにして App.css ファイル内でフォントをインポートしてください:

@import url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');

では、ヘッダーのフォントを変更しましょう。

    <div className="main">
      <h2 className="main-header">React Crud Operations</h2>
    </div>

このように、見出しタグの className 属性の値を、main-header に設定してください。

それから、App.css 内で、Montserrat フォントファミリーを追加してください:

.main-header{
  font-family: 'Montserrat', sans-serif;
}
Screenshot-2021-07-24-132749-1

これでヘッダーが変更されたのが確認できます。

CRUD コンポーネントを作成する方法

これから、4 つの CRUD 操作 (Create - 生成、Read - 読み取り、Update - 更新、Delete - 削除) に対応するコンポーネントを作成してみましょう。

src フォルダーの中に、components というフォルダーを作成してください。それから、このフォルダーの中に create、read、update という 3 つのファイルを作成してください。delete については、コンポーネントを追加する必要はありません。

Screenshot-2021-07-24-133242

では、Create (生成) 操作を実装しましょう。

ただそのためには、Mock API を使用する必要があります。この API は作成したデータを偽のサーバーへ送信するもので、単に学習目的で使用します。

それでは、https://mockapi.io/ へアクセスし、アカウントを作成してください。

mockAPI
MockAPI

プラスボタンをクリックしてプロジェクトを作成してください。

createProject
プラスボタンをクリックして新しいプロジェクトを作成
projectName

プロジェクトの名前を入力して、CREATE ボタンをクリックしてください。

newResorce

NEW RESOURCE ボタンをクリックして新しいリソースを作成してください。

resorceName

Resorce Name の欄へ名前を入力することを求められますので、使用する名前を入力してください。

resorceNameFakeData-1

name、avatar、createdAt などの余分な欄は必要ありませんので削除してください。その後で、CREATE をクリックしてください。

createFakeAPI

これで、fakeData という名前の、偽の API を作成できました。

fakeData の上でクリックすると、新しいタブで API が開くのを確認できます。現在データベースは空です。

Create コンポーネント用のフォームを作成する方法

次に、Semantic UI ライブラリーが提供しているフォームを使用してみましょう。

Semantic UI React へアクセスし、左側の検索バーの中で Form を検索してください。

SemanticReactForm

このようなフォームが表示されるので、上部左側の Try it をクリックして、コードを取得してください。

FormCode

コードをコピーしたら、次のように create.js ファイルの中に貼り付けてください:

import React from 'react'
import { Button, Checkbox, Form } from 'semantic-ui-react'

const Create = () => (
    <Form>
        <Form.Field>
            <label>First Name</label>
            <input placeholder='First Name' />
        </Form.Field>
        <Form.Field>
            <label>Last Name</label>
            <input placeholder='Last Name' />
        </Form.Field>
        <Form.Field>
            <Checkbox label='I agree to the Terms and Conditions' />
        </Form.Field>
        <Button type='submit'>Submit</Button>
    </Form>
)

export default Create;

では、Create コンポーネントを App.js ファイルの中でインポートしてください。

import './App.css';
import Create from './components/create';

function App() {
  return (
    <div className="main">
      <h2 className="main-header">React Crud Operations</h2>
      <div>
        <Create/>
      </div>
    </div>
  );
}

export default App;

そうすると次のようになります:

formInit

しかし、ここで問題が発生します – 項目が適切にそろえられていませんし、テキスト入力欄のラベルの色が黒になってしまっています。では、これを修正してみましょう。

create.js ファイルの中で、Form の className の値を create-form に設定してください。

import React from 'react'
import { Button, Checkbox, Form } from 'semantic-ui-react'

const Create = () => (
    <Form className="create-form">
        <Form.Field>
            <label>First Name</label>
            <input placeholder='First Name' />
        </Form.Field>
        <Form.Field>
            <label>Last Name</label>
            <input placeholder='Last Name' />
        </Form.Field>
        <Form.Field>
            <Checkbox label='I agree to the Terms and Conditions' />
        </Form.Field>
        <Button type='submit'>Submit</Button>
    </Form>
)

export default Create;
create.js

そして、 App.css ファイルの中に以下のクラスセレクターを追加してください:

.create-form label{
  color: whitesmoke !important;
  font-family: 'Montserrat', sans-serif;
  font-size: 12px !important;
}
App.css

このクラスセレクターはフォームの各欄のラベルを指定して、文字色を whitesmoke に設定しています。また、フォントを変更して、フォントサイズを大きくしています。

では、main という className のセレクターの中で、flex-direction プロパティーを追加してください。このプロパティーの値を column 方向に設定することで、className が main である要素の中の各要素が、垂直にそろえられます。

.main{
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #212121;
  color: whitesmoke;
  flex-direction: column;
}
App.css
columnDirectionForm

これで、フォームの外観が改善されるのが確認できます。

では次に、フォーム欄からデータを取得してコンソールの中で表示してみましょう。そのために、React の useState フックを使用します。

create.js ファイルの中で、React から useState をインポートしてください。

import React, { useState } from 'react';

その後で、First Name、Last Name、チェックボックス用のステート (state) を作成してください。各ステートは、空のストリングまたは false で初期化します。

import React, { useState } from 'react';
import { Button, Checkbox, Form } from 'semantic-ui-react'

export default function Create() {
    const [firstName, setFirstName] = useState('');
    const [lastName, setLastName] = useState('');
    const [checkbox, setCheckbox] = useState(false);
    return (
        <div>
            <Form className="create-form">
                <Form.Field>
                    <label>First Name</label>
                    <input placeholder='First Name' />
                </Form.Field>
                <Form.Field>
                    <label>Last Name</label>
                    <input placeholder='Last Name' />
                </Form.Field>
                <Form.Field>
                    <Checkbox label='I agree to the Terms and Conditions' />
                </Form.Field>
                <Button type='submit'>Submit</Button>
            </Form>
        </div>
    )
}

現在、Create コンポーネントは関数コンポーネントとして機能しているのが確認できます。フックは、関数コンポーネントの中だけで使用できるので、コンポーネントを関数コンポーネントに変更する必要があります。

では、First Name、Last Name、チェックボックスの各欄の値を、setFirstNamesetLastNamesetCheckbox プロパティーを用いて、それぞれ設定しましょう。

<input placeholder='First Name' onChange={(e) => setFirstName(e.target.value)}/>

<input placeholder='Last Name' onChange={(e) => setLastName(e.target.value)}/>

<Checkbox label='I agree to the Terms and Conditions' onChange={(e) => setCheckbox(!checkbox)}/>

それから、firstName、lastName、checkbox の各ステートの値を取得してみましょう。

ここで、後から API へデータを送信するのに使用する、postData という名の関数を作成します。その関数の中に、次のコードを記述してください:

const postData = () => {
        console.log(firstName);
        console.log(lastName);
        console.log(checkbox);
}

では、First Name、Last Name、チェックボックスの値をコンソールに出力してみましょう。

Submit ボタンに、onClick イベントを使用してこの関数を割り当てることによって、Submit ボタンを押したときに、この関数が呼び出されるようにします。

<Button onClick={postData} type='submit'>Submit</Button>

これまでの内容をすべて含んだ、create ファイル用のコードはこちらです:

import React, { useState } from 'react';
import { Button, Checkbox, Form } from 'semantic-ui-react'

export default function Create() {
    const [firstName, setFirstName] = useState('');
    const [lastName, setLastName] = useState('');
    const [checkbox, setCheckbox] = useState(false);
    const postData = () => {
        console.log(firstName);
        console.log(lastName);
        console.log(checkbox);
    }
    return (
        <div>
            <Form className="create-form">
                <Form.Field>
                    <label>First Name</label>
                    <input placeholder='First Name' onChange={(e) => setFirstName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <label>Last Name</label>
                    <input placeholder='Last Name' onChange={(e) => setLastName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <Checkbox label='I agree to the Terms and Conditions' onChange={(e) => setCheckbox(!checkbox)}/>
                </Form.Field>
                <Button onClick={postData} type='submit'>Submit</Button>
            </Form>
        </div>
    )
}

First name と Last name の中に値を入力して、チェックボックスにチェックを入れてください。その後で、Submit ボタンをクリックしてみてください。すると次のように、コンソールの中にデータがポップアップするのが確認できます:

dataPopUp

Axios を使って API リクエストを Mock API へ送信する方法

今度は、Axios を使ってフォームのデータを偽のサーバーへ送信してみましょう。

しかしまずは、Axios をインストールする必要があります。

npm i axios と入力して、パッケージをインストールしてください。

AxiosInstall

パッケージのインストールが終了したら、Create 操作の実装を開始しましょう。

Axios をファイルの先頭でインポートしてください。

import axios from 'axios';
Axios のインポート

postData 関数の中で、Axios を使用して POST リクエストを送信します。

const postData = () => {
        axios.post(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData`, {
            firstName,
            lastName,
            checkbox
        })
}
POST リクエストの送信

ご覧のとおり、ここでは axios.post を使用しています。また axios.post の中に、先ほど作成した API のエンドポイントがあります。その後に、中括弧で囲まれたフォームの項目があります。

Submit をクリックした時に、この関数が呼び出され API サーバーにデータを送信します。

postFormData

では、First Name と Last Name を入力して、チェックボックスにチェックを入れたら、Submit をクリックしてください。

postedFormData

その後で API を確認してみると、オブジェクトの中に囲まれた状態で、入力した First Name と Last Nameの値と、true という値に設定された checkbox を取得できます。

Read 、Update、Delete の各操作を実装する方法

Read (読み取り) 操作の実装を開始するために、Read ページを作成する必要があります。また、React Router パッケージを用いて、ユーザーをさまざまなページへ案内する必要があります。

https://reactrouter.com/web/guides/quick-start へアクセスし、また、npm i react-router-dom@5 を使用してパッケージをインストールしてください。

パッケージのインストールが済んだら、React Router からコンポーネントをいくつかインポートします:

import { BrowserRouter as Router, Route } from 'react-router-dom'
React Router から Router と Route をインポート

App.js の中で、return の中のコードをすべて Router でラップしてください。基本的に Router の内部にあるものは、 React の中でルーティングを使用できることを意味しています。

import './App.css';
import Create from './components/create';
import { BrowserRouter as Router, Route } from 'react-router-dom'

function App() {
  return (
    <Router>
      <div className="main">
        <h2 className="main-header">React Crud Operations</h2>
        <div>
          <Create />
        </div>
      </div>
    </Router>
  );
}

export default App;

現在、App.js は上のような状態でしょう。

では、return 内の Create を置き換えて、以下のコードを追加してください:

import './App.css';
import Create from './components/create';
import { BrowserRouter as Router, Route } from 'react-router-dom'

function App() {
  return (
    <Router>
      <div className="main">
        <h2 className="main-header">React Crud Operations</h2>
        <div>
          <Route exact path='/create' component={Create} />
        </div>
      </div>
    </Router>
  );
}

export default App;

ここでは、Create をルートコンポーネントとして使用しています。Create のパスは '/create' に設定しました。そのため、http://localhost:3000/create へアクセスすれば、Create ページを見ることができます。

同じように、read と update に対応するルートが必要です。

import './App.css';
import Create from './components/create';
import Read from './components/read';
import Update from './components/update';
import { BrowserRouter as Router, Route } from 'react-router-dom'

function App() {
  return (
    <Router>
      <div className="main">
        <h2 className="main-header">React Crud Operations</h2>
        <div>
          <Route exact path='/create' component={Create} />
        </div>
        <div style={{ marginTop: 20 }}>
          <Route exact path='/read' component={Read} />
        </div>

        <Route path='/update' component={Update} />
      </div>
    </Router>
  );
}

export default App;

上のコードで確認できるように、read と update のルートを作成します。

ここで http://localhost:3000/read へアクセスすると、Read ページが次のように表示されます:

planeReadComponent
Read ルート

また、http://localhost:3000/update では、次のように Update コンポーネントが表示されます:

planeUpdateComponent

Read 操作

Read 操作には、テーブルコンポーネントが必要です。そのため、React Semantic UI にアクセスし、ライブラリーが提供しているテーブルを、以下のように使用してください。

import React from 'react';
import { Table } from 'semantic-ui-react'
export default function Read() {
    return (
        <div>
            <Table singleLine>
                <Table.Header>
                    <Table.Row>
                        <Table.HeaderCell>Name</Table.HeaderCell>
                        <Table.HeaderCell>Registration Date</Table.HeaderCell>
                        <Table.HeaderCell>E-mail address</Table.HeaderCell>
                        <Table.HeaderCell>Premium Plan</Table.HeaderCell>
                    </Table.Row>
                </Table.Header>

                <Table.Body>
                    <Table.Row>
                        <Table.Cell>John Lilki</Table.Cell>
                        <Table.Cell>September 14, 2013</Table.Cell>
                        <Table.Cell>jhlilk22@yahoo.com</Table.Cell>
                        <Table.Cell>No</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Jamie Harington</Table.Cell>
                        <Table.Cell>January 11, 2014</Table.Cell>
                        <Table.Cell>jamieharingonton@yahoo.com</Table.Cell>
                        <Table.Cell>Yes</Table.Cell>
                    </Table.Row>
                    <Table.Row>
                        <Table.Cell>Jill Lewis</Table.Cell>
                        <Table.Cell>May 11, 2014</Table.Cell>
                        <Table.Cell>jilsewris22@yahoo.com</Table.Cell>
                        <Table.Cell>Yes</Table.Cell>
                    </Table.Row>
                </Table.Body>
            </Table>
        </div>
    )
}
read.js

ここではテーブルの中にいくつかのダミーデータが用いられていますが、1 列分のデータだけが必要なので、残りは削除しましょう。

import React from 'react';
import { Table } from 'semantic-ui-react'
export default function Read() {
    return (
        <div>
            <Table singleLine>
                <Table.Header>
                    <Table.Row>
                        <Table.HeaderCell>Name</Table.HeaderCell>
                        <Table.HeaderCell>Registration Date</Table.HeaderCell>
                        <Table.HeaderCell>E-mail address</Table.HeaderCell>
                        <Table.HeaderCell>Premium Plan</Table.HeaderCell>
                    </Table.Row>
                </Table.Header>

                <Table.Body>
                    <Table.Row>
                        <Table.Cell>John Lilki</Table.Cell>
                        <Table.Cell>September 14, 2013</Table.Cell>
                        <Table.Cell>jhlilk22@yahoo.com</Table.Cell>
                        <Table.Cell>No</Table.Cell>
                    </Table.Row>
                </Table.Body>
            </Table>
        </div>
    )
}
read.js
reducedRows

これが Read ページの出力画面です。テーブルには列が 4 つありますが、必要なのは 3 つだけです。

余分な項目の列を削除してから、次のように項目の名前をつけなおしてください:

reducedColumn

すると現在、Read ページはこのように見えます:

import React from 'react';
import { Table } from 'semantic-ui-react'
export default function Read() {
    return (
        <div>
            <Table singleLine>
                <Table.Header>
                    <Table.Row>
                        <Table.HeaderCell>First Name</Table.HeaderCell>
                        <Table.HeaderCell>Last Name</Table.HeaderCell>
                        <Table.HeaderCell>Checked</Table.HeaderCell>
                    </Table.Row>
                </Table.Header>

                <Table.Body>
                    <Table.Row>
                        <Table.Cell>Nishant</Table.Cell>
                        <Table.Cell>Kumar</Table.Cell>
                        <Table.Cell>Yes</Table.Cell>
                    </Table.Row>
                </Table.Body>
            </Table>
        </div>
    )
}
read.js

では、API から GET リクエストを送信してデータを取得してみましょう。

アプリケーションがマウントされる時に、取得したデータが必要になるので、useEffect フックを使用して実装してください。

import React, { useEffect } from 'react';

 useEffect(() => {
       
 }, [])
useEffect フック

ステートを 1 つ作成して、取得したデータを格納します。取得するデータは配列です。

import React, { useEffect, useState } from 'react';

const [APIData, setAPIData] = useState([]);
useEffect(() => {
       
}, [])
取得した API データを格納する APIData ステート

では、useEffect フックの中で、GET リクエストを送信してみましょう。

 useEffect(() => {
        axios.get(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData`)
            .then((response) => {
                setAPIData(response.data);
            })
    }, [])

ここでは axios.get を使用して、GET リクエストを API へ送信しています。その後で、リクエストが resolve (成功) すれば、レスポンスデータを APIData ステート内に格納します。

続いて、取得した API データに応じてテーブルの行をマッピングしましょう。

そのために Map 関数を使用します。Map 関数は配列を反復処理して、データを出力画面内に表示します。

<Table.Body>
  {APIData.map((data) => {
     return (
       <Table.Row>
          <Table.Cell>{data.firstName}</Table.Cell>
           <Table.Cell>{data.lastName}</Table.Cell>
           <Table.Cell>{data.checkbox ? 'Checked' : 'Unchecked'}</Table.Cell>
        </Table.Row>
   )})}
</Table.Body>

API 内のデータに応じて、firstName, lastName, checkbox のそれぞれのデータをマッピングしています。また、ここでは三項演算子 ('?') を使用しています。data.checkbox が true である場合は、Checked と表示され、そうでない場合は Unchecked と表示されます。

ReadOutput
read.js の出力画面

Update 操作

それでは、テーブルに Update (更新) 用のヘッダーをもう 1 つ作成し、Update ボタン用の列を、Table.Row の中に作成してください。Update ボタンには、Semantic UI React が提供している Button コンポーネントをインポートして使用してください。

<Table.HeaderCell>Update</Table.HeaderCell>

<Table.Cell> 
  <Button>Update</Button>
</Table.Cell>
Update ボタンの作成

ここで、Update ボタンがクリックされた時に、 Update ページにリダイレクトされる必要があります。そのためには React Router が提供している Link が必要です。

では、React Router から Link をインポートしてください。それから、Link タグの中へ Update ボタン用の Table.Cell をラップしてください。

import { Link } from 'react-router-dom';

<Link to='/update'>
  <Table.Cell> 
     <Button>Update</Button>
   </Table.Cell>
</Link>
Update ボタン用の Link

これで、Update ボタンをクリックした時に、Update ページへリダイレクトされるようになりました。

また、Update ボタンをクリックした時に、各列のデータを更新するには、API が提供している、それぞれの ID が必要です。

setData という名前の関数をコンポーネントの先頭に作成してください。それから、その関数を Update ボタンにバインドしてください。

 <Button onClick={() => setData()}>Update</Button>

ここでは、先頭の関数へ引数としてデータを渡す必要があります。

 <Button onClick={() => setData(data)}>Update</Button>

そして、先頭の関数の中で、データをコンソール内に表示させます:

const setData = (data) => {
   console.log(data);
}
updateDataInConsole
コンソール内のデータ

では、update ボタンをクリックして、コンソールを確認してみてください。テーブルの各項目のデータを取得しています。

今度は、このデータをローカルストレージへ格納しましょう。

const setData = (data) => {
        let { id, firstName, lastName, checkbox } = data;
        localStorage.setItem('ID', id);
        localStorage.setItem('First Name', firstName);
        localStorage.setItem('Last Name', lastName);
        localStorage.setItem('Checkbox Value', checkbox);
}
ローカルストレージ内へデータを格納

このようにして、データを id、firstName、lastName、checkbox に分割してから、ローカルストレージへ格納しています。ローカルストレージを使用することで、ブラウザー内でローカルにデータを保存できます。

今ここで、Update コンポーネント内に update 操作用のフォームが 1 つ必要です。Create コンポーネントで用いたフォームを再利用しましょう。関数名を単に Create から Update へ変更するだけです。

import React, { useState } from 'react';
import { Button, Checkbox, Form } from 'semantic-ui-react'
import axios from 'axios';

export default function Update() {
    const [firstName, setFirstName] = useState('');
    const [lastName, setLastName] = useState('');
    const [checkbox, setCheckbox] = useState(false);

    return (
        <div>
            <Form className="create-form">
                <Form.Field>
                    <label>First Name</label>
                    <input placeholder='First Name' onChange={(e) => setFirstName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <label>Last Name</label>
                    <input placeholder='Last Name' onChange={(e) => setLastName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <Checkbox label='I agree to the Terms and Conditions' onChange={(e) => setCheckbox(!checkbox)}/>
                </Form.Field>
                <Button type='submit'>Update</Button>
            </Form>
        </div>
    )
}
Update ページ

useEffect フックを Update コンポーネント内で作成してください。このフックを使い、前もってローカルストレージへ格納したデータを取り出します。さらに、ID 項目用のステートをもう一つ作成します。

const [id, setID] = useState(null);

useEffect(() => {
        setID(localStorage.getItem('ID'))
        setFirstName(localStorage.getItem('First Name'));
        setLastName(localStorage.getItem('Last Name'));
        setCheckbox(localStorage.getItem('Checkbox Value'))
}, []);

それから、ローカルストレージから取り出したデータを、キーに応じて配置します。フォームの各欄の中に、取り出した値を配置する必要があります。Update ページがロードされた時に、各欄の中にデータが自動的に配置されるようにしましょう。

<Form className="create-form">
                <Form.Field>
                    <label>First Name</label>
                    <input placeholder='First Name' value={firstName} onChange={(e) => setFirstName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <label>Last Name</label>
                    <input placeholder='Last Name' value={lastName} onChange={(e) => setLastName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <Checkbox label='I agree to the Terms and Conditions' checked={checkbox} onChange={(e) => setCheckbox(!checkbox)}/>
                </Form.Field>
                <Button type='submit'>Update</Button>
            </Form>
フォームの各欄の中に値を配置

これで、Read ページ内の Update ボタンをクリックすると、Update ページへリダイレクトされ、そこで自動的に配置されたフォームデータを見ることができます。

populatedDataInUpdatePage
Update ページ

それでは、Update リクエストを実装してデータを更新してみましょう。

updateAPIData という名前の関数を作成してください。この関数の中で、axios.put を用いて PUT リクエストを送信し、データを更新します。

const updateAPIData = () => {
    axios.put(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData/${id}`, {
        firstName,
         lastName,
         checkbox
	})
}

ここでは API エンドポイントに id 項目を添えているのが確認できます。

Read ページで、項目の Update ボタンをクリックした時に、その ID がローカルストレージの中に格納され、その後に Update ページ で取り出した ID を id ステートの中に格納しています。

そうした後に、id をエンドポイントへ渡しています。こうすることで、渡している ID の項目を更新できます。

次に、updateAPIData 関数を Update ボタンにバインドしてください。

<Button type='submit' onClick={updateAPIData}>Update</Button>
updateAPIData を Update ボタンにバインド

Read ページにあるテーブルの中の、Update ボタンをクリックしてから、Last name を変更し、Update ページにある Update ボタンをクリックしてください。

updatingTheFields
Last Name 項目の更新

API を確認してみるか、または Read ページへ戻ってみると、last name が変更されているのを確認できます。

updatedMockAPIData
変更された Mock API のデータ
updatedReadTable
Read ページのテーブル

Delete 操作

まずは、Read ページのテーブルに、Delete  (削除) 操作用のボタンを 1 つ追加しましょう。

<Table.HeaderCell>Delete</Table.HeaderCell>

<Table.Cell>
   <Button>Delete</Button>
</Table.Cell>
Read ページのテーブル内に Delete ボタンを追加

次に、onDelete という名前の関数を作成してから、Delete ボタンにその関数をバインドしてください。この関数は、Delete ボタンをクリックした時に ID パラメータを受け取ります。

const onDelete = (id) => {

}

<Table.Cell>
   <Button onClick={() => onDelete(data.id)}>Delete</Button>
</Table.Cell>
Delete 操作用の関数

では、axios.delete を使用して、それぞれの項目を削除する操作を実装しましょう。

const onDelete = (id) => {
  axios.delete(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData/${id}`)
}
API から項目を削除

Delete ボタンをクリックしてから API を確認してみてください。クリックした項目のデータが削除されているのを確認できます。

ここで、クリックした項目のデータが削除された後に、テーブルのデータをロードし直す必要があります。

そのために、API のデータを読み込む関数を作成してください。

const getData = () => {
    axios.get(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData`)
        .then((getData) => {
             setAPIData(getData.data);
         })
}
API のデータを取得

そして onDelete 関数の中で、項目を削除した後に更新された API のデータを読み込む必要があります。

const onDelete = (id) => {
        axios.delete(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData/${id}`)
     .then(() => {
        getData();
    })
}
項目を削除した後に更新された API のデータを読み込む
ReadTableBeforeDataDeleted
Read ページのテーブル

これで、今は各項目の Delete ボタンをクリックすることでその項目が削除され、テーブルが自動的に最新の情報に更新されます。

ReadTableAfterDataDeleted
項目が 1 つ削除された後の Read ページのテーブル

CRUD アプリを少し改善してみましょう

これまで、Create ページの中でデータを投稿 (post) する時には、単にデータを偽のデータベースの中へ入れていましたが、その際に Read ページへリダイレクトする必要があります。

それではまず、React Router から useHistory をインポートしてください。

import { useHistory } from 'react-router';
React Router から useHistory をインポート

次に、let 文で history という名前の変数を作成して、その変数の中に useHistory を格納してください。

let history = useHistory();

その後で、post API が呼び出されてから、POST リクエストが resolve した時に、history.push 関数を使用して Read ページへ移動します。

const postData = () => {
        axios.post(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData`, {
            firstName,
            lastName,
            checkbox
        }).then(() => {
            history.push('/read')
        })
    }
Post API が resolve した後で Read ページへ移動する

このように useHistory フックを用いることで Read ページへ移動できます。

Update ページについても同じことを行ってください。

import React, { useState, useEffect } from 'react';
import { Button, Checkbox, Form } from 'semantic-ui-react'
import axios from 'axios';
import { useHistory } from 'react-router';

export default function Update() {
    let history = useHistory();
    const [id, setID] = useState(null);
    const [firstName, setFirstName] = useState('');
    const [lastName, setLastName] = useState('');
    const [checkbox, setCheckbox] = useState(false);

    useEffect(() => {
        setID(localStorage.getItem('ID'))
        setFirstName(localStorage.getItem('First Name'));
        setLastName(localStorage.getItem('Last Name'));
        setCheckbox(localStorage.getItem('Checkbox Value'));
    }, []);

    const updateAPIData = () => {
        axios.put(`https://60fbca4591156a0017b4c8a7.mockapi.io/fakeData/${id}`, {
            firstName,
            lastName,
            checkbox
        }).then(() => {
            history.push('/read')
        })
    }
    return (
        <div>
            <Form className="create-form">
                <Form.Field>
                    <label>First Name</label>
                    <input placeholder='First Name' value={firstName} onChange={(e) => setFirstName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <label>Last Name</label>
                    <input placeholder='Last Name' value={lastName} onChange={(e) => setLastName(e.target.value)}/>
                </Form.Field>
                <Form.Field>
                    <Checkbox label='I agree to the Terms and Conditions' checked={checkbox} onChange={() => setCheckbox(!checkbox)}/>
                </Form.Field>
                <Button type='submit' onClick={updateAPIData}>Update</Button>
            </Form>
        </div>
    )
}
Update.js

以上で、React と React フックを使用して CRUD 操作を実行する方法について理解できました!

学習内容を補足したい場合は、React CRUD Operations という YouTube のビデオ を、この記事の代わりに見ることができます。

さらに、コードをテストしてみたい場合は、GitHubでコードを見つけることができます。

ハッピーラーニング