20200625のReactに関する記事は9件です。

Docker TypeScript で React 環境を構築

自分用のmemoのつもりで
Dockerで環境構築
Dockerはinstall済み

■Dockerfile作成
空のPJディレクトリ内にDokerfile作成し以下を記載

FROM node:13.5.0-alpine3.11
WORKDIR /usr/src/app

FROMは新しいイメージの元となるイメージの読み込み
alpineというのでめちゃくちゃファイルサイズを小さくできるらしい

■docker-compose.yml作成
※ymlは「yaml ain't markup language」の略で構造化データの表現方法
※簡単に言えば設定ファイル

version: '3'
services:
  sample:
    build:
      context: .
    tty: true
    environment:
      - NODE_ENV=production
    volumes:
      - ./:/usr/src/app
    command: sh -c "cd tips && yarn start"
    ports:
      - "3000:3000"

■イメージをビルド

docker-compose build

■React と create-react-app をインストール + アプリ作成

docker-compose run --rm sample sh -c 'npx create-react-app sample_app --template typescript'

出来上がるディレクトリ 構成

- Dockerfile
- docker-compose.yml
- アプリ名
    |- node_module
    |- public
    |- src

■起動

docker-compose up -d

※ローカルでyarn startする時よりも時間がかかる感覚はある

Localhost:3000でApp.jsの中身が表示される

■停止

docker-compose stop
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

僕が考えた最強の React 技術スタック

開発

フレームワーク

  • Next.js
    • $ npx create-next-app
    • with-typescript-eslint-jest を選択すると、いい感じに色々入る

状態管理

フォーム

コンポーネントフレームワーク

HTTP クライアント

Firebase

ユニットテスト

開発補助

スタイルガイド

  • Storybook
    • $ npx -p @storybook/cli sb init --type react

Linter

Formatter

環境変数

気になってる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[1行で完了]最速でReact環境構築

※自分のアウトプット用(メモ)です

結論だけ知りたい人用

1行のコマンドでReactの環境構築を完了する。
[条件]
1.Node.js 8.10以上
2.npm 5.6以上

$ npx create-react-app プロジェクト名

順番通り説明していきます。

必要なパッケージのインストール方法

1. brewをインストール

Macのパッケージ管理システムであるbrewをインストール。
brew公式サイト

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

2. nodebrewbrewでインストール

nodeのバージョン管理ができるnodebrewをインストール。
(brewでインストールするので先にbrewをインストールした)。

$ brew install nodebrew

3. Node.jsnodebrewを使ってインストール

Node.jsはnodebrewで管理した方が使いやすいと思います。他のバージョンに移るの簡単ですし、普通にインストールすると削除するのに手間なんですよね...
ほとんどの場合、安定版をインストールしておけば問題ないと思います。

// リモートにあるインストールできるNode.jsの一覧表示
$ nodebrew ls-remote

// 安定版をローカル(自分のMac)にインストール
$ nodebrew install stable

// ローカルにインストールされている`Node.js`のバージョンを一覧表示
$ nodebrew ls

// インストールしたバージョンの`Node.js`を選択する
$ nodebrew use 使用したいバージョン番号

4. Node.jsのパスを通す

// "~/.bash_profile"にパスを追記する(bashの場合)
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile

// ターミナルを再起動して反映
// または以下を実行して反映
$ source ~/.bash_profile

5. nodenpmが使用可能か確認

Node.jsをインストールした時点でnpm(node package manager)もインストールされているので、うまくいっていればこの時点で使用可能になっているはずです。

// Node.js
$ node -v

// npm
$ npm -v

これで準備は整いました。

create-react-appReactの環境構築

任意の場所で以下のコマンドを叩いてください。
npxコマンドを簡潔に説明すると、パッケージをローカルにインストールすることなく実行できるコマンドです。
環境を汚染しないので手軽に実行して見たいときに便利です。
詳細はこちら

$npx create-react-app プロジェクト名

これでカレントディレクトリにreactのプロジェクトが作成されました。
以下のコマンドでブラウザ表示します。

$ npm start

スクリーンショット 2020-06-25 15.21.19.png

お疲れ様でした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React Hooksを使ったモーダル実装

React HooksのuseState・useRefを使ったモーダル実装についてまとめました。

今回実装するのは、以下のようなモーダルになります。

ezgif.com-video-to-gif (2).gif

完成コード

React

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

const App = () => {
  const [modal, setModal] = useState(false)
  const modalRef = useRef()

  return (
    <div>
      <button onClick={() => setModal(true)}>Open</button>
      <div className={`modal__overlay ${modal && "is-opened"}`}  onClick={e=>{if(modalRef.current === e.target) setModal(false)}} ref={modalRef}>
        <div className="modal__box">
          <button className="modal__closeBtn" onClick={() => setModal(false)}>×</button>
          <div>モーダルテキスト</div>
        </div>
      </div>
    </div>
  );
}

export default App;

CSS

.modal__overlay{
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0,0,0,0.4);
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s, visibility .3s;
}
.is-opened{
  visibility: visible;
  opacity: 1;
}
.modal__box{
  background-color: #fff;
  position: relative;
  padding: 30px 20px;
}
.modal__closeBtn{
  position: absolute;
  top: 0;
  right: 0;
}

実装流れ

1.モーダルの見た目作成

まず、オーバーレイ要素(画面全体を覆う薄暗い要素)とモーダルボックスを作成します。

import React from 'react';

const App = () => {
  return (
    <div>
      {/* オーバーレイ要素でモーダルボックスを囲む */}
      <div className="modal__overlay">
        <div className="modal__box">
          <div>モーダルテキスト</div>
        </div>
      </div>
    </div>
  );
}

export default App;

.modal__overlay{
  /* 画面全体を覆う設定 */
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0,0,0,0.4);
  z-index: 999;
  /* 画面中央にモーダルを表示させる設定 */
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal__box{
  background-color: #fff;
  padding: 30px 20px;
}

ここまでの実装画面
スクリーンショット 2020-06-25 11.01.21.png

2.モーダルの表示切り替えの実装

次に、ボタンクリックでモーダルの表示・非表示を切り替えます。

// useState追加
import React, {useState} from 'react'; 

const App = () => {
  // モーダルの表示・非表示をstate管理(true:表示 false:非表示)
  // ※modal:現在のstate値 setModal:state値を更新するための関数 false:初期値
  const [modal, setModal] = useState(false)

  return (
    <div>
      {/* ボタンクリック後、modalをtrueに変更 */}
      <button onClick={() => setModal(true)}>Open</button>
      {/* modalがtrueの場合、is-openedクラスを付与 */}
      <div className={`modal__overlay ${modal && "is-opened"}`}>
        <div className="modal__box">
          {/* ボタンクリック後、modalをfalseに変更 */}
          <button className="modal__closeBtn" onClick={() => setModal(false)}>×</button>
          <div>モーダルテキスト</div>
        </div>
      </div>
    </div>
  );
}
.modal__overlay{
  z-index: 999;
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0,0,0,0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  /* 初期状態は非表示 */
  opacity: 0;
  visibility: hidden;
  /* ゆっくり表示させる */
  transition: opacity .3s, visibility .3s;
}
/* モーダル表示(modalがtrueになったら付与される) */
.is-opened{
  visibility: visible;
  opacity: 1;
}
.modal__box{
  background-color: #fff;
  padding: 30px 20px;
  position: relative;
}
.modal__closeBtn{
  position: absolute;
  top: 0;
  right: 0;
}

ここまでの実装画面
ezgif.com-video-to-gif (4).gif

3.オーバーレイクリックでモーダルを閉じる処理

最後に、オーバーレイをクリックした時にもモーダルを閉じるようにしたいと思います。

<div className={`modal__overlay ${modal && "is-opened"}`}  onClick={() => setModal(false)}>

このように追記することで、オーバーレイクリック後にモーダルを閉じることができますが、これだとモーダルボックス内をクリックした時にも閉じてしまいます。
ezgif.com-video-to-gif (5).gif
そこで、コンポーネントのDOMノードに直接アクセスできるようになるuseRefフックを使用します。

// useRef追加
import React, {useState, useRef} from 'react';

const App = () => {
  // modalRefの定義 ※modalRef.currentでオーバーレイ要素を取得可能に
  const modalRef = useRef()
  const [modal, setModal] = useState(false)

  return (
    <div>
      <button onClick={() => setModal(true)}>Open</button>
      {/* クリックした要素がmodalRef.currentと一致した場合、modalをfalseに変更 */}
      <div className={`modal__overlay ${modal && "is-opened"}`} onClick={e=>{if(modalRef.current === e.target) setModal(false)}} ref={modalRef}>
        <div className="modal__box">
          <button className="modal__closeBtn" onClick={() => setModal(false)}>×</button>
          <div>モーダルテキスト</div>
        </div>
      </div>
    </div>
  );
}

export default App;

完成

ezgif.com-video-to-gif (2).gif

このようにuseState・useRefを使用することで簡単にモーダル実装ができますので、是非お試し下さい!

参考文献

https://chaika.hatenablog.com/entry/2019/12/08/090000
https://ichiki.netlify.app/blog/20191218_react_click_out/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

このチュートリアルでは、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ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初心者向け]Reactができるようになりたい ~React Hooksについて~

はじめに

今回はReactのHooksについてまとめていきます。

頑張っていきましょう。

今回は以下の記事を参考にしました。

日本一わかりやすいReact入門#8...React Hooksでstateを扱おう

React Hooks超入門

最近Reactを始めた人向けのReact Hooks入門

Hookとは

Hookとは、端的に言えばクラスコンポーネントの機能をFunctionalコンポーネントでも使えるようにするためのものです。

具体的には、今まではクラスコンポーネントでしか持つことができなかったstateやライフサイクルをFunctionalコンポーネントで利用できるようになります。

今までReactの様々な機能にアクセスできるクラスコンポーネントと違い、一切のアクセスが許可されていなかったFunctionalコンポーネントをReactの機能へ接続(Hooks into)するという意味で、Hooksと呼ぶらしいです。

なぜHookを使うのか

察しの良い皆さんならこう思ったはずです。

「stateやライフサイクルメソッドが使いたいならクラスメソッド使えば良くね?」

確かに一理あります。

しかし、クラスコンポーネントには以下で示すような問題がありました。

  • 処理が散らばりやすい
  • thisを使いたくない
  • 複数のライフサイクルメソッドに処理がまたがるのが嫌だ
  • そもそもクラスコンポーネントの構文が複雑
  • stateの扱い方が複雑

この中のいくつかの問題点を、さらに深く解説していきます。

処理が散らばりやすい

Reactを書いたことがある皆さんなら共感頂けると思いますが、クラスコンポーネントはメソッドをいくつも実装できるが故に処理が散り散りになりやすいんですよね。

子供のコンポーネントで行われる処理を、親のクラスコンポーネントのライフサイクルに定義して使いたくなりますよね。

具体例で話すなら、例えば人間コンポーネントを定義して、それに子供としてハサミコンポーネントを渡したとします。

このハサミコンポーネントの前に紙が存在するときに、ハサミコンポーネントの切断という機能を実装したいとします。

人間コンポーネントをクラスコンポーネント、ハサミコンポーネントをFunctionalコンポーネントだとすると、はstateを持つ人間コンポーネントで管理することになりますし、紙の状態に応じた処理(ここでは切断する)もライフサイクルを持つ人間コンポーネントの中で書くことになりそうです。

子供のコンポーネントがハサミコンポーネントのみならまだしも、他の様々なコンポーネントのstateやライフサイクルも人間コンポーネントで管理することになると、非常に煩雑になりそうですよね。

そもそも、切断するという処理はハサミコンポーネントの中の処理であるので、当然の思考としてハサミコンポーネントの中で管理するのが良さそうです。

また、というstateも、紙の状態に応じたライフサイクルを用いた処理も、人間コンポーネントではなくハサミコンポーネントで管理するべきですよね。

ここでハサミコンポーネントをクラスコンポーネントにしてしまっても良いのですが、それだと根源的な解決になりません。

そもそも、ひとつの機能はひとつの場所にという原則を守って書くことを強制してしまった方が良さそうです。

そこで導入されたのがHookであり、Functionalコンポーネント自体にstateやライフサイクルを管理させるとうものです。

thisを使いたくない

Javascriptにおけるthisは、他の言語におけるthisとは違う挙動をします。

詳しくは以下の記事を御覧ください。

JavaScriptの「this」は「4種類」??

JavaScript の this を理解する多分一番分かりやすい説明

つまり、簡単に書くとthisの使い方めっちゃむずいということです。

こんなものはトラブルの元です。

できるだけ使わないようにしようという動きも多く、そのためクラスコンポーネントはできるだけ使いたくないと思う人も多いようです。

複数のライフサイクルメソッドに処理がまたがるのが嫌だ

クラスコンポーネントのライフサイクルメソッドは、時間の流れで処理を分割します。

そうすると、同じような機能が複数のライフサイクルメソッドに跨ってしまうことがありますよね。

そのように記述するよりも、同じ機能は同じ場所と言う方が分かりやすいと考える人も多いようです。ちなみに私もそう思います。

React-Hooksの実装

それでは実際いHooksを実装してみましょう。

Hooksでstateの管理

まず、Hooksでstateの管理をしていきます。

HooksはFunctionalコンポーネントにおけるstateの管理やライフサイクルメソッドの実装に用いるんでしたね。

Hooksでstateを用いるときは、useStateというメソッドを使います。

実際にコードで確認してみましょう。

今回は、ScissorsコンポーネントというFunctionalコンポーネントを作成して、それを親コンポーネントであるAppコンポーネントから呼び出します。

そのScissorsコンポーネントにcuttingとうstateを持たせて、ボタンを押すことで変化させるという機能を実装します。

以下がコードです。

App.jsx
import React from 'react';
import Scissors from './Scissors'

const App = () => {

  return(
    <div>
      <Scissors />
    </div>
  )
}
export default App

これはシンプルにScissorsコンポーネントを呼び出しているだけですね。以下がそのScissorsコンポーネントです。

Scissors.jsx
import React, { useState } from 'react';

const Scissors = () => {
    const [cutting, changeCutting] = useState("NoCutting");
    return(
        <div>
            <h1>{cutting}</h1>
            <button onClick={() => changeCutting("YesCutting!")}>change </button>
        </div>
    )
}

export default Scissors

それではHooksの部分を解説していきます。

以下の部分でuseStateをインポートしています。

import React, { useState } from 'react';

これでインポートすることができました。

次の部分が、useStateを使う上で肝となる部分です。以下のコードです。

const [cutting, changeCutting] = useState("NoCutting");

それでは解説します。

cuttingがstateであり、changeCuttingがstateを変更させる関数です。ちなみに、このchangeCuttingに引数を渡して実行すれば、cuttingの値がその引数に渡した値に変化します。

つまり、このuseState関数は、statestateを変更させる関数を同時に定義していると考えることができますね。

クラスコンポーネントでは、constructorの部分でthis.state = {}という感じにstateを定義し、setStateを用いてそのstateを変更していたと思います。

それでは、useStateの引数の部分は何を意味するのでしょうか。

正解は、stateの初期値になります。

つまり、上のコードはcuttingというstateを作成し、その初期値にNoCuttingを渡し、それと同時にそのstateを変更させる関数であるchangeCuttingを作成したことになります。またこのchangeCuttingは、実行したときにcuttingの値を引数に指定した値に変更させる関数になります。

以下のコードで、ボタンをクリックしたときにこのchangeCuttingを実行しています。

<button onClick={() => changeCutting("YesCutting!")}>change </button>

buttonタグのonClickにアロー関数としてchangeCuttingを実行したものを渡しています。

onClickはボタンをクリックしたときに引数として渡された関数を実行するという機能なので、このように関数そのものを渡します。

実際にこのReactアプリの挙動を見てみましょう。

temp3.gif

ここまでで、Hooksによるstate管理は終わりです。

Hooksによるライフサイクルの管理

Hooksによるライフサイクルメソッドの代替として、useEffectメソッドがあります。

以下の三つのメソッドを代替することができます。

  • coponentDidMount()
  • componentDidUpdate()
  • componentWillUnmount()

軽く解説します。

componentDidMountについて

componentDidMountはマウントが行われた直後に実行されるメソッドです。Ajaxを使ったデータフェッチ(初回)やイベントリスナのセットなどを行います。

componentDidUpdateについて

componentDidUpdateはstateの更新が行われた直後に行われるメソッドです。具体的には、stateが更新され、その後にrenderが走った後に呼び出されます。

stateがある閾値を超えたときに別の動作をするようにしたいときなどに使うと便利ですね。

componentWillUnmountについて

componentWillUnmountは、コンポーネントが破棄される直前に呼び出されます。

具体的には、イベントリスナーを解除してメモリを開放するときなどに利用されます。

それでは、実際にuseEffectメソッドを用いてこれらのライフサイクルメソッドを実装してみましょう。

useEffectメソッドの実装

まず、最初にuseEffectメソッドの使い方解説を行います。

以下の記事を参考にしました。

【React】useEffectの第2引数って?

第一引数のみ

第二引数を空っぽにすると、第一引数に指定したコールバック関数がrender毎に実行されます。

componentDidUpdateと同じタイミングで呼ばれることになりますね。

useEffect(() => {
  console.log("render")
});

しかし、これは公式のリファレンスで推奨されていない書き方なので、使わないようにしましょう。

第二引数を与える

空の配列が渡されたとき

useEffect(() => {
  console.log('mounting')
}, [])

第二引数に殻の配列が渡された場合、マウント時とアンマウント時のみ、第一引数に渡されたコールバック関数を実行します。

Reactはrenderが呼ばれるたびに第二引数の値がrender前とrender後に変化したかどうかを確認します。

その時、変化していた場合にのみ第一引数に設定したコールバック関数を実行します。

今回は、第二引数に空の配列を指定しているため、マウント時のみ第一引数のコールバック関数が走るようになります。

componentDidMountと同じタイミングになります。

第二引数の配列に値が渡された場合

第二引数に値の配列が渡された場合、renderの前後で値が変化した場合に第一引数のコールバック関数が呼ばれます。

const [Boolean, changeBoolean] = useState(true)
useEffect(() => {
  console.log('changed')
}, [Boolean])

この場合、第二引数に渡したBooleanの値が変更されるたびに第一引数に渡したコールバック関数が呼ばれるようになります。

マウント時とアンマウント時のみ実行

useEffectメソッドにおいては、第一引数のコールバック関数内においてreturnを行うと、そのreturnの中の処理がアンマウント時に実行されるようになります。

以下のコードです。

useEffect(() => {
  console.log("render")
  return () => {
    console.log("Unmounting!")
  }
}, []}

第二引数に空の配列を渡しているので、render毎に実行されることはありません。

つまり、console.log("render")の部分がマウント時のみ実行されるようになります。

また、return後の関数が、アンマウント時に実行されるようになります。

終わりに

今回の記事はここまでになります。

お疲れさまでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PropsとStateの違い

Reactを学習していて、PropsとStateの違いってなんやろ
とふとした時に思い調べました。

学習メモなのでふわっとしていますが、どうぞよしなに。

*間違いがあれば教えていただけると、ありがたいです。

【Propsとは】
・オブジェクト
・親コンポーネントからもらう値
・Propsを受け取る側の子コンポーネントではPropsを変化させれない
・親コンポーネントから変化させられる

【Stateとは】
・オブジェクト
・コンポーネント自身で定義する
・初期値を設定したらsetStateでStateの値を変更する

<まとめ>

Props→上から下に流れるデータ
State→コンポーネント自身が持つデータ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ReactでSemantic Uiを 使ってみる

■semantic ui react

yarn add semantic-ui-react

※フォントを変えたいのでsemantic-cssは読み込まない

LESSを読むためにcracoをインストール

yarn add @craco/craco @semantic-ui-react/craco-less semantic-ui-less --dev

Package JSONを書き換え

{
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "craco eject"
  }
}

craco.config.jsを作成

module.exports = {
  plugins: [{ plugin: require('@semantic-ui-react/craco-less') }],
}

必要なbuildツールをインストール

npx @semantic-ui-react/bootstrap

インストールされた新しいフォルダ内にあるtheme.configの設定を変更
src/semantic-ui/theme.config

/*******************************
            Folders
*******************************/

@themesFolder : 'themes';
@siteFolder  : '../../src/semantic-ui/site';


/*******************************
         Import Theme
*******************************/

@import (multiple) "~semantic-ui-less/theme.less";
@fontPath : '../../../themes/@{theme}/assets/fonts';

Index.jsでimport

import 'semantic-ui-less/semantic.less'

font の変更

src/semantic-ui/site/globals/site.variables
@headerFont        : 'Muli', 'Noto Sans JP', sans-serif;
@pageFont          : 'Muli', 'Noto Sans JP', sans-serif;
@googleFontFamily  : 'Noto+Sans+JP:wght@300;400;700|Muli:wght@300;400;700';
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

node.jsでvercelを使って環境変数を設定するメモ

環境変数設定メモ

vercel では、環境変数を本番環境、プレビュー環境、および開発環境用に簡単に分けることができる。


手順

1. vercle プロジェクト設定の[ 全般]ページ に移動して、[環境変数] セクションを見つける。

スクリーンショット 2020-06-25 1.12.55.png

2.環境変数の名前を入力する。

たとえば、Node.jsを使用していて、SENTRY_KEYという名前の環境変数を作成すると、コード内でprocess.env.SENTRY_KEYで使用できるようになる。

環境 説明
Production 環境変数が次の本番デプロイメントに適用される。本番デプロイメントを作成するには、デフォルトのブランチにcommitをpushする。
Preview 環境変数は、プレビューデプロイメントに適用される。プレビューデプロイメントは、ブランチ(例えば my-new-feature )にpushすると作成される。
Development 環境変数は、プロジェクトをローカルで、vercel dev または任意の開発コマンドで実行するときに使用する。開発環境変数をダウンロードするには、vercel env pull を実行する。


これだけ!


Enjoy Hacking!:sunglasses:

参考

https://vercel.com/docs/v2/build-step?query=envirome#development-environment-variables

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む