LoginSignup
7
9

More than 3 years have passed since last update.

AdonisJSとReactを使ってイベントを管理するためのモダンなWebアプリを構築する

Last updated at Posted at 2020-06-25

このチュートリアルでは、ReactとAdonis Node.jsフレームワークを使って、Alibaba Cloud上でREST APIのバックエンドとフロントエンドを構築します。

本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。

序章

Adonisは、スケーラブルで安定した効率的なWebアプリケーションやREST APIを構築するために使用できるNode.jsフレームワークです。Reactを使用して、Adonisで構築されたREST APIを消費するためのモダンで堅牢なフロントエンドWebアプリケーションを構築します。

これから構築するWebアプリケーションは、MySQLのデータベースにイベントを格納し、これらのイベントを読み込んで削除します。

完成したら、以下のことができるようになります。

  • Adonis.jsを使ったREST APIの構築
  • Reactを使ってREST APIを消費する堅牢なクライアントサイドアプリケーションを構築する
  • Bootstrap 4とReactを統合する

前提条件

このガイドを始める前に、以下のものが必要です。

  • Ubuntu 18.04を搭載したElastic Compute Service (ECS)開発マシン。
  • Node.js 8.0.0.0+とNpm 3.0.0.0+がマシンにインストールされている。
  • ローカルにインストールされたMySQL 5.7+。

ステップ1 - Adonis APIプロジェクトの作成と依存関係のインストール

このステップでは、Adonisプロジェクトを足場にするのに役立つAdonis CLIをインストールし、アプリケーションのデータベース接続をセットアップするために必要な依存関係をインストールします。

ターミナルを開き、以下のコマンドを実行してAdonis.js CLIをグローバルにインストールします。

npm i -g @adonisjs/cli

これでインストールが完了したら、ターミナルのどこからでもadonisを実行できるようになるはずです。以下のコマンドを実行して、インストールしたCLIのバージョンを確認することで試すことができます。

adonis --version

次に、新しいAdonisアプリケーションを足場にする必要があります。任意のディレクトリに移動し、以下のコマンドを実行します。

adonis new adonis-events --api-only

新しいコマンドは adonis-events という新しいプロジェクトを足場にし、--api-only は生成されたプロジェクトが特に REST API 用であることを指定します。新しいコマンドは、新しいプロジェクトに必要なすべての npm 依存関係をインストールします。

生成されるプロジェクトは以下のような構造になっているはずです。

image.png

次に、データベース接続を設定する必要があります。Adonis は多くの SQL データベースをサポートしていますが、使用する特定のデータベース、この場合は MySQL 用のパッケージをインストールする必要があります。プロジェクトフォルダに移動し、以下のコマンドを実行します。

npm i --save mysql

このプロジェクトでは、.envというファイルにアプリケーションを設定するための環境変数が含まれています。データベース接続が mysql に設定されていることを確認してください。

[~/adonis-events/.env]
...
DB_CONNECTION=mysql
...

最後に、このプロジェクトで使用する MySQL データベースをローカルに作成する必要があります。ローカルにMySQLがインストールされている場合は、以下のコマンドを実行してデータベースを作成します。

mysql -u root
mysql> CREATE DATABASE events;

新しいデータベースを作成したら、.env ファイルの資格情報を作成したデータベースと一致するように更新します。

[~/adonis-events/.env]
...
DB_CONNECTION=mysql
DB_USERNAME=root
DB_DATABASE=events
DB_PASSWORD=
...

これが完了したら、REST APIとReactフロントエンドの作成に進みます。

ステップ2 - Reactフロントエンドを作成する

このステップでは、Reactを使ってアプリケーションのフロントエンドを作成します。webpack の設定や本番のビルドプロセスを気にすることなく、React アプリケーションを素早く足場にするために、crease-react-app という人気のあるパッケージを使用します。ローカルにcreate-react-appがインストールされていない場合は、以下のコマンドを実行してください。

npm i -g create-react-app

インストールしたら、新しいフォルダに移動し、以下のコマンドを実行して新しいReactプロジェクトを作成します。

create-react-app adonis-events-react

新たに生成されたReactプロジェクトの構造は以下のようになります。

image.png

新しく作成したReactプロジェクトを起動するには、Reactプロジェクトディレクトリに移動し、以下のコマンドを実行します。

npm start

これにより開発サーバーが起動し、デフォルトのブラウザで以下のようなReactアプリケーションが開くはずです。

image.png

最後に、基本的なスタイリングを行うためのBootstrap CSSフレームワークをインストールしてみましょう。

Reactプロジェクト内のsrcフォルダに入り、index.cssファイルを開きます。このファイルの内容を以下のように置き換えます。

[~/adonis-events-react/src/index.css]
@import 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';

上記は、ブートストラップCSSファイルへのリンクをインポートしたもので、フロントエンドプロジェクトのスタイルを素早く設定するために使用できるすべてのスタイルとクラスが含まれています。

フロントエンドアプリケーションのセットアップが完了したので、データベースモデルと移行を開発しましょう。

ステップ3 - イベントの移行とモデルの作成

このステップでは、データベーステーブルをどのように構造化するかを決定する移行をセットアップし、このデータベーステーブルとの対話に役立つモデルをセットアップします。

まず、ターミナルでAdonisアプリケーションに移動し、次のコマンドを実行します。

adonis make:model Event -m

このコマンドは、モデルとそれに対応するマイグレーションを素早く作成する方法です。以下のような出力が得られます。

 create  app/Models/Event.js
 create  database/migrations/1541120387036_event_schema.js

作成したファイルは2つで、app/Models/Event.jsはこんな感じです。

'use strict'

const Model = use('Model')

class Event extends Model {
}

module.exports = Event

これは基本的なES6のクラスで、ベースとなるModelクラスを継承しています。見ての通り、このクラスには多くの静的メソッドがあり、データベースと簡単にやりとりするのに役立ちます。

2つ目のファイルは、database/migrations/1541120387036_event_schema.jsで、以下のようになっています。

'use strict'

const Schema = use('Schema')

class EventSchema extends Schema {
  up () {
    this.create('events', (table) => {
      table.increments()
      table.timestamps()
    })
  }

  down () {
    this.drop('events')
  }
}

module.exports = EventSchema

Adonisのマイグレーションは、ベースのSchemaクラスを拡張したES6クラスで、2つの重要なメソッドを含んでいます:upは、データベーステーブルの作成や変更を含むデータベースへの変更を行うために使用され、downはそれらの変更を反転させるために使用されます。up関数では、データベーステーブルの構造を記述するAdonisが提供するメソッドを呼び出します。

現時点では、up関数の中の関数this.create('events')がデータベース内にイベントテーブルを作成します。また、down関数のthis.drop('events’)は、必要に応じてデータベース内のイベントテーブルを削除します。

イベントテーブルには以下のフィールドがあります。

  • title - イベントのタイトル
  • start_date - イベントの開始日.
  • end_date - イベントの終了日.
  • location - 偶数の場所
  • price - イベントの費用

マイグレーションでは、以下のようにこれらのフィールドを定義します。

次に、このマイグレーションファイルを実行して、Adonisが接続されたデータベースにこれらの変更を影響させることができるようにする必要があります。

プロジェクトフォルダにあることを確認し、以下のコマンドを実行してください。

adonis migration:run

以下のような出力が表示されるはずです。

migrate: 1503250034279_user.js
migrate: 1503250034280_token.js
migrate: 1541120387036_event_schema.js
Database migrated successfully in 206 ms

このコマンドを実行すると、Adonisは各マイグレーションファイルを読み込み、これらのファイル内でup機能を実行します。したがって、現時点では、私たちのデータベースには、userstokenseventsの3つのテーブルが新たに作成されています。最初の2つのテーブルは、Adonisの新規インストール時にデフォルトで出荷されます。

データベースのセットアップが完了したら、REST APIの作成に進みます。

ステップ4 - REST APIの作成

このステップでは、REST APIを作成します。イベントに対するさまざまなアクションを処理するために、いくつかの API エンドポイントを作成します。作成するエンドポイントは以下の通りです。

  • [POST] /api/events は、イベントを作成
  • [DELETE] /api/events/:idは、 特定のイベントを削除
  • [GET] /api/eventsは、すべてのイベントのリストを取得

[POST]/api/eventsエンドポイントの実装

まずは、これらのエンドポイントを処理するためのコントローラを生成することから始めましょう。コントローラは基本的に ES6 クラスで、すべてのビジネスロジックを処理するメソッドを含んでいます。以下のコマンドを実行してください。

adonis make:controller EventController

以下のような出力が表示されるはずです。

> Select controller type For HTTP requests
 create  app/Controllers/Http/EventController.js

次に、この特定のエンドポイントを扱うルートを登録する必要があります。start/routes.jsファイルを開き、以下を追加します。

Routeクラスにはpostという静的関数があり、このメソッドはpostエンドポイントを登録します。最初のパラメータはパス、api/events、2番目のパラメータはこのエンドポイントへのリクエストを処理するコントローラとメソッドです。この場合、EventControllerstore メソッドです。つまり、このメソッドを作成する必要があります。EventControllerのように追加します。

Adonis は context と呼ばれるオブジェクトを注入しますが、この context には request オブジェクトと response オブジェクトを含む、requestに関する多くの関数とオブジェクトが含まれており、requestオブジェクトにはrequestに関するすべての情報が含まれています。現時点でのstoreメソッドでは、request.all()関数を呼び出すと、POSTリクエストで送信された全てのデータを返してくれます。今回は、イベントを作成するために、リクエストデータにtitle、start_date、end_date、location、priceが提供されていることを想定しています。

次に、このデータをデータベースに保存しなければなりません。データベース、特にeventsテーブルと通信するために、モデルを使用します。eventsモデルを使用すると、Adonisは自動的にeventsテーブルに接続します。

eventsモデルを使用して、create関数を呼び出しました。これは、POSTリクエストから取得したデータを使用して、自動的に新しい行をeventsデータベーステーブルに保存します。この関数は新しく作成されたイベントを返し、このeventsと一緒にJSONレスポンスを返します。

: Adonisのuse関数はNode.jsのrequire関数のラッパーです。これは名前空間を使用し、上で行ったようにファイルを簡単にrequireするのに役立ちます。ですから、require('../.../.../Models/Event.js’)の代わりに、単に use('App/Models/Event') と書きます。

先ほど実装した/POSTエンドポイントを試してみましょう。そのためには、Adonis APIを実行する必要があります。

以下のコマンドでadonisサーバーを実行します。

adonis serve --dev
info: serving app on http://127.0.0.1:3333

新しく作成したPOST /api/eventsエンドポイントを試すために、任意のRESTクライアントを使用することができます。今回はPOSTMANを使ってみます。

操作結果は以下の通りです。

image.png

:POSTMANではContent-typeapplication/jsonに設定することを忘れないでください。

[取得] api/eventsエンドポイントの実装

このエンドポイントのルートを追加してみましょう。routes.jsファイルで、次のように追加します。

[~/adonis-events/start/routes.js]

Route.get(api/events', 'EventController.index')

これはエンドポイントを EventControllerindexメソッドにマッピングします。このコントローラでは、次のように追加してみましょう。

indexメソッドは、eventsモデルのall()関数を使用してeventsテーブルからデータベースのすべての行を取得します。これをPOSTMANで試してみると、以下のような結果が得られるはずです。

image.png

[削除] api/events/:id エンドポイントの実装

最後に実装しなければならないエンドポイントは、イベントを削除するためのものです。このエンドポイントはこれまでの他のエンドポイントとは少し異なり、動的パラメータを使用します。このエンドポイントのルートを登録してみましょう。

[~/adonis-events/start/routes.js]

Route.delete(api/events/:id', 'EventController.delete')

ルートの :id は動的パラメータで、削除したいイベントの特定の id を渡すことができます。このルートを EventControllerdelete メソッドにマッチさせます。

delete メソッドでは、ルートから取得した動的 ID を使用してイベントを検出し、検出されたイベントに対して delete 関数を呼び出します。以下に POSTMAN でのテストの様子を示します。

image.png

それだけです。Adonisで完全に機能するAPIを作るのはこんなに簡単なことなのです。フロントエンドに切り替える前にもう一つ。現時点では、Adonis APIは他のサーバーやドメインからのリクエストを許可しません。これはCORS保護と呼ばれるもので、不正なリクエストがAPIに行われないようにするために本当に重要です。この特定のケースでは、ReactフロントエンドがAPIリクエストを行うことを許可するようにAdonisに指示しなければなりません。これを行うには、Adonisには設定ファイルが既に設定されているので、アプリケーションのCORS設定を変更することができます。config/cors.jsに移動して、このファイルをこのように修正します。

[~/adonis-events/config/cors.js]

  origin: ['http://localhost:3000'],

ここでは、すべての認可されたオリジンの配列を作成し、この配列にリストされたすべてのドメインがAdonisアプリケーションにAPIリクエストを行うことができるようになります。クライアント側のReact開発サーバーのドメインは http://localhost:300 なので、これをorigin配列に追加しました。

次のステップでは、Reactフロントエンドに切り替えて、堅牢なクライアントサイドアプリケーションを構築するために、このデータの消費を開始しましょう。

ステップ5 - クライアントサイドコンポーネントを設定する

最初に設定するコンポーネントは、App コンポーネントです。これは、最初にアプリケーションにアクセスしたときに表示されるコンポーネントです。他の不要なファイルもすべてクリーンアップします。

不要なファイルを削除した後の現在のフォルダ構造は以下の通りです。

image.png

次に、単一のイベントを表現するために使用するコンポーネントを作成してみましょう。プロジェクトフォルダに移動し、srcフォルダ内にEvent.jsというファイルを作成します。

このコンポーネントは、現時点での静的データを表示し、単一のイベントを表示するためのテンプレートを表しています。

最後に、AddEvent.jsという別のファイルを作成します。これは、新しいイベントを追加するためのフォームとして機能します。

必要なコンポーネントの作成が完了したので、APIサービスを作成してみましょう。

ステップ6 - Axios APIサービスの作成

Adonis API と通信できるようにするために、シンプルな HTTP クライアントを使用します。このクライアントをインストールするには、Reactプロジェクトに移動し、次のコマンドを実行します。

npm install axios --save

これをインストールしたら、src フォルダに apiService.js というファイルを作成し、以下のクラスを追加します。

このクラスは axios のシンプルなラッパーであり、Adonis API への HTTP リクエストを行うためのヘルパー関数を提供します。コンストラクタでは、すべてのリクエストのBaseURLをAdonisアプリケーションのURLに設定します。

サービスの準備ができたので、これらのコンポーネントを機能させてみましょう。

ステップ7 - イベントの作成

イベントを作成するために、Create Eventボタンを用意します。ユーザーがこのボタンをクリックすると、イベントを作成するためのフォームを持つコンポーネントが表示されます。Appコンポーネントを以下のように変更してみましょう。

現時点では以下のようになっています。

image.png

まず、AddEventコンポーネントをインポートしました。showCreateEventFormというステート・プロパティを設定し、レンダー関数の中で、このプロパティが真であればAddEventコンポーネントをマウントし、そうでなければマウントしません。Create Eventボタンがクリックされると、このステート・プロパティの値を切り替えます。また、showCreateEventFormtrue の場合は Create Event ボタンに btn-danger クラスを動的に追加し、このプロパティが false の場合は btn-info を追加します。

次のステップは、このフォームを実際に動作させて、ユーザーがイベントの詳細を入力して保存できるようにすることです。

イベントの作成機能の実装

最初のステップは、ユーザーが入力した入力を取得することです。これを管理するためにステートを使います。ここにAddEvent.jsコンポーネントのアップデート版があります。

この時点では、入力フィールドが変更されるたびに、その値は自動的にこのコンポーネントの状態に設定されます。

現時点では、デフォルトのブラウザの日付ピッカーを使用しており、これには時間ピッカーが統合されていません。さらに、この日付ピッカーの動作はブラウザによって非常に一貫性がありません。そこで、start_dateend_dateのフィールドには、FlatPickrと呼ばれるサードパーティ製の日付ピッカーを使用します。この日付ピッカーをインストールするには、以下のコマンドを実行します。

npm i --save react-flatpickr

インストールできたら、このようにフォームを修正してみましょう。

まず、インストールしたFlatPickrコンポーネントをインポートします。前回の日付入力の代わりに、FlatPickrをマウントし、handleDateChangeと呼ばれる別のハンドラを渡します。これはほとんど同じことを行い、start_dateend_dateの値が変更されたときの状態に設定します。

さて、このイベントを保存するためのAPIリクエストを実際に行う時が来ました。これを行うために、Appコンポーネントから関数を渡し、呼び出されたときにイベントを保存します。Appコンポーネントをこのように修正してみましょう。

コンポーネントをこのように更新してみましょう。

まず、ApiServiceをインポートし、Appコンポーネントのコンストラクタで新しいインスタンスを作成します。次に、apiServiceからの関数であるstoreEventというAddEventコンポーネントにプロップを渡します。

次に、AddEventコンポーネントのCreate Eventボタンが作成された際に、このプロップを呼び出す必要があります。

Create Eventボタンがクリックされると、this.props.storeEvent()を呼び出し、状態をパラメータとして渡します。この関数は axios を呼び出し、イベントを保存するための HTTP リクエストを行います。開発者ツールで発信HTTPリクエストを確認すると、AdonisサーバーからのHTTPレスポンスが表示されているはずです。

すべてのイベントのリストが表示されるまでは、作成されたことを確信することはできませんよね?次のステップでは、Adonis APIからすべてのイベントのリストをフェッチして表示します。

すべてのイベントをフェッチして表示する

すべてのイベントを取得するために、コンポーネントがマウントされた直後に [GET] リクエストを行い、結果を取得したら、その結果をステートに設定してコンポーネントに表示します。これを実現するために、componentDidMountというReactのライフサイクルフックを追加してみましょう。この関数は、コンポーネントがマウントされるとすぐに実行されます。

まず、イベントという新しいステートプロパティを空の配列に設定します。次に、componentDidMount関数の中で、APIリクエストをしてすべてのイベントを取得し、レスポンスが返ってきたら、その結果をstateに設定します。この時点でReact Dev toolsなどのツールを使ってコンポーネントの状態を検査すると、すべてのイベントのリストが表示されているはずです。

次のステップは、このイベントのリストをコンポーネントに表示することです。このために作成したEventコンポーネントを使用します。App コンポーネントをこのように変更してみましょう。

各イベントをマッピングして、1つのイベントを所定の場所に表示します。現時点では、アプリケーションがマウントされると、対応するイベントのリストが表示されるはずです。

image.png

イベント コンポーネントはまだ動的ではありません。これは、特定のイベント(Appコンポーネントから渡された)のためのプロップを受け取り、代わりにそれらを表示する必要があります。この動作をサポートするように変更してみましょう。

これで、各イベントはeventプロップを介して渡されたカスタムデータを表示するようになりました。

現時点では、イベントを作成しても何も起こりません。より良いエクスペリエンスを得るために、App コンポーネントを修正して、AddEvent フォームを非表示にし、すべてのイベントを再度取得して、ユーザーが新しく作成されたイベントを見ることができるようにします。

最初に、fetchEventsという新しい関数を作成します。次に、storeEventという新しい関数を作成します。この関数はAPIを呼び出して新しいイベントを保存し、レスポンスを取得したらfetchEventsを呼び出してすべてのイベントを取得し、toggleShowCreateEventFormを呼び出してcreateイベントフォームを非表示にします。

ステップ8 - Deleteイベントの実装

最後のタスクは、イベントを削除できるようにすることです。App コンポーネント上でイベントを削除する関数を作成し、この関数をEvent コンポーネントのプロップとして渡し、ユーザーが削除ボタンをクリックするたびにこの関数が呼び出されます。Appコンポーネントは次のようになります。

新しく追加された関数deleteEventはAPIサービスを呼び出し、イベントが削除されると、再びfetchEventsを呼び出して、すべてのイベントの新鮮なコピーを取得します。最後に、Eventコンポーネントで、idパラメータを指定してこの関数を呼び出します。このようにEventコンポーネントを修正します。

すべての変更を行った後のプロジェクトの動作は次のようになります。

image.png

このアプリケーションが完成したことで、実際のプロジェクトの参考として使用できる最新のフルスタックJavascriptアプリケーションの基礎を手に入れることができます。

結論

このチュートリアルでは、Adonis.jsとReact.jsを使ってフルスタックのJavascriptデモアプリケーションを作成しました。REST APIの構築にはAdonis.js、APIの消費にはReact、アプリケーションのスタイリングにはBootstrap 4を使用しました。Adonis REST APIのソースコードはこちらのGitHubリポジトリに、ReactフロントエンドアプリケーションのソースコードはこちらのGitHubリポジトリにあります。

Adonisフレームワークについてもっと詳しく知りたい場合は、公式ドキュメントがとても便利で、ビデオチュートリアルも提供されています。

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ

7
9
1

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
7
9