0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Reactハンズオン 備忘録 - 実践編

Posted at

はじめに

今回のハンズオン勉強会ではレシピ一覧を表示するサンプルコードを用意しました。

Repository

モックサーバー、リスト表示コンポーネントが既に実装されているので、そこにRating機能を追加するといった内容のハンズオンを実施しました。

サンプルコードの実行方法

前提条件

  • Git
  • node.js ≧ v14
    • npm
    • @stoplight/prism-cli(入っていない場合は後の手順で導入)

ローカルにサンプルコードを落とす

以下のコマンドでGitからソースコードを落として、プロジェクトのディレクトリを移動、必要なパッケージのダウンロードまでをやってくれるので、コピペして各自のシェルで実行してください。

git clone https://github.com/koki-2424/react-hands-on-learn.git
cd react-hands-on-learn/client
npm i

プロジェクト構成については以下のようになっていますので、落としたプロジェクトをVS Code(各自のエディター)で開いてみてください。

C:\
|
|─client
|  ├─App.jsx # 一番上にあるコンポーネント、ルーティングを実装
|  ├─index.css
|  ├─index.js # entry point for all node apps
│  ├─public
│  └─src
│      ├─api
│      ├─components # UIの部品、各ページで使いまわせるように設計するのが理想
│      └─pages # どのPageコンポーネントを呼ぶかはApp.jsxのpagesコンポーネントで定義している
└─server # モックサーバーを配置
    └─data

モックサーバーの起動

モックサーバーを起動する。
@stoplight/prism-cliは入っていない人のみ実行

npm install -g @stoplight/prism-cli
npm run server

フロントエンドの起動

npm run start

Reactコンポーネント

以下のHelloは一番シンプルなReactコンポーネントです。
JSX式で書かれているため見慣れないかもしれませんが、これはシンプルなJavaScript関数です。

以下のHelloコンポーネントはプロパティとしてデータを渡しています。
Reactでは関数でいう引数のことをプロパティと呼び、これはRead onlyなデータとなります。
プロパティだけでは動的なデータをコンポーネントの中で扱うことができず、これだけでは実務で使えるアプリケーションの構築をすることはできません。

// 引数として渡されている"message"がプロパティ
function Hello({message}) {
    return <div>{message}</div>
}

<Hello message="hello world!" />

それに対して、描画後に変更できるデータをステートと呼びます。
ステートを導入することで、よりインタラクティブなアプリケーションを構築することができるようになります。

※Reactでは他ファイルで使いたいコンポーネントがあるときは、exportしてファイル外から呼び出し可能にして、importすることで他ファイルのコンポーネントを呼び出すことができます。サンプルコードにはexport, importの記述がありますが、深い意味はなく他ファイルから呼び出すための記述だと理解してください。

ステート管理

サンプルデータのvalue[n].rateにRating機能のための数値データを用意しました。
このデータを使ってReactのステート管理の仕組みを試しましょう。

StarRatingコンポーネントを配置する

react-hands-on-learn\client\src\pages\RecipeList.jsxで定義したStarRatingコンポーネントを使ってRating機能を実装する。

作成済のコードは星の色を固定値で書いているため、以下のように色を切り替えられるStarコンポーネントを新しく定義してください。

const Star = ({selected = false}) => (
    <FaStar color={selected ? "yellow" : "grey"} />
)

上のように定義することでselectedプロパティの値によって異なる色の星を描画することができます。
レーティングのUIは星5であることが多いですが、Starコンポーネントを別に定義しておくことで星10で細かなレーティングをできるようにしたい。といった要求に答えられるようになります。
新しくStarコンポーネントを定義したのでStarRatingコンポーネントを以下のように書き換えてください。

function StarRating({totalStars = 5}){
  return [...Array(totalStars)].map((_, i) => <Star key={i} />);
}

これで、デフォルトで5つの星を表示するコンポーネントが作成できました。
試しにRecipeListコンポーネントに配置してみてください。

useStateフックを使ってクリックイベントに対応する

関数コンポーネントでステートを実装する場合はReactが提供するフックという機能を使います。

今回の勉強会では関数コンポーネントについてしか触れていないのですが、Reactにはクラスコンポーネントとして定義する方法もあります。
クラスコンポーネントを使う場合は、フックではなくライフサイクルメソッドを使ってコンポーネントの状態管理を行います。
2019年2月のReactのアップデートがされてからは、クラスコンポーネントではなく、関数コンポーネントを使う方が主流になると考えられます。

ここではStarRatingコンポーネントにステートを追加したいのでuseStateというフックを使います。
以下のようにコードを書き換えてください。

import { useState } from 'react';

const Star = ({ selected = false, onSelect = f => f }) => (
  <FaStar color={selected ? "yellow" : "grey"} onClick={onSelect} />
)

function StarRating({ totalStars = 5 }) {
  // selectedStarsにはデフォルト値"0"がセットされる
  // setSelectedStarsにはselectedStarsを更新するメソッドがセットされる
  const [selectedStars, setSelectedStars] = useState(0);

  return (
    <>
      <div className='flex'>
        {[...Array(totalStars)].map((_, i) => (
          <Star key={i}
            selected={selectedStars > i}
            onSelect={() => setSelectedStars(i + 1)} />
        ))}
      </div>
      <p>{selectedStars} of {totalStars} stars</p>
    </>
  )
}

export default StarRating;

上記のコードでは、StarコンポーネントにonSelectプロパティを追加しています。onSelectは関数で、そのままFaStarコンポーネントのonClickイベントのハンドラとして設定されています。
それにより、星のアイコンがクリックされたことを親コンポーネントへ伝えることができる。

上記の例ではuseState()の返り値が二つの変数に代入されている。

  const [selectedStars, setSelectedStars] = useState(0);

この書き方はReactで頻繁にされるものででストラクチャリングと呼ばれている。

JavaScript Document: Destructuring assignment

RecipeListにRating機能を追加してください。

書き換える場所は以下です。

function List({ data = [], renderEmpty }) {
  if (!data) return renderEmpty;
  return (
    <div>
      {data.map((item, i) => (
        <div class="max-w-md py-4 px-8 bg-white shadow-lg rounded-lg my-20">
          <div>
            <h2 class="text-gray-800 text-3xl font-semibold">{item.name}</h2>
            <p class="mt-2 text-gray-600">{item.description}</p>
          </div>
          <div class="flex items-stretch">
            <div className='flex-1 mt-4'><p>{item.rate}</p></div>
            <div className='flex-1 text-right mt-4'>
              <a href="#" class="text-xl font-medium text-indigo-500">Detail</a>
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

参考文献

今回の勉強会は「Reactハンズオンラーニング」の内容をもとにしています。
本日は「Reactの基本」、「関数の作成」、「ステート管理」から30ページほどを抜き出して学習しました

本の構成としては以下のようになっていてJavaScriptの基礎から学べるので誰にでもおすすめな書籍です。
今回の勉強会で少しでも興味のある方は是非読んでみてください。

  • Reactの全体像: 最初5ページ
  • JavaScriptの基礎(関数型プログラミング, オブジェクト, 非同期処理...):約 1 / 6
  • Reactの基本から環境構築まで:約 1 / 6ページ
  • ステート管理、フック:約 1 / 3
  • データ通信について:約 1 / 6
  • Reactの将来、Reactライブラリについて:約 1/ 3
    • サスペンス
    • テスト
    • ルーティング
    • サーバーサイド
      • Next.js, Gatsby
0
0
0

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?