🐣

Reactをはじめてみた 5日目。

2023/07/01に公開

Reactをはじめてみた。

誰にも参考にならないかもしれない。
5日目 >>3時間ぐらいの学習時間

今日の学習資料

https://ja.react.dev/learn/thinking-in-react

Reactの流儀

ユーザーインターフェイスの構築

  1. UIをコンポーネントに分割
  2. コンポーネントの視覚的状態を記述
  3. 複数のコンポーネントを接続し、データが流れるようにする

条件

  • モックアップがもらえていること
    • Json APIが実装済みであること
      (サーバーにurl アクセスして帰ってくるjsonのことかな?)
[
  { category: "Fruits", price: "$1", stocked: true, name: "Apple" },
  { category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
  { category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
  { category: "Vegetables", price: "$2", stocked: true, name: "Spinach" },
  { category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin" },
  { category: "Vegetables", price: "$1", stocked: true, name: "Peas" }
]

とりあえずphpで上のjson 返すもの作成しておく

192.168.12.34/json_api/index.php?name=api

index.php
<?php

    if (!empty($_GET["name"]) && $_GET["name"] =="api") {
        $data = Array(
            array("category" => "Fruits", "price" => "$1", "stocked" => true, "name"=> "Apple" ),
            array("category" => "Fruits", "price" => "$1", "stocked" => true, "name"=> "Dragonfruit" ),
            array("category" => "Fruits", "price" => "$2", "stocked" => false, "name"=> "Passionfruit" ),
            array("category" => "Vegetables", "price"=> "$2", "stocked" => true, "name"=> "Spinach" ),
            array("category" => "Vegetables", "price"=> "$4", "stocked" => false, "name"=> "Pumpkin" ),
            array("category" => "Vegetables", "price"=> "$1", "stocked" => true, "name"=> "Peas" )
        );
        header('Content-Type: application/json');
        $data = json_encode($data);
        if (json_last_error() == JSON_ERROR_NONE){
            echo $data;
        } else {
        http_response_code(500);
    }
}

?>
  • ローカルにサーバー立てて、下記にアクセスで json 帰ってくるようにした。
    192.168.12.34/json_api/index.php?name=api

Reactプロジェクトの作成

$ npm create vite@latest
$ cd tutorial-moc
$ npm install
$ npm run dev

1. UI をコンポーネントの階層に分割する

  1. FilterableProductTable(灰色)はアプリ全体のコンテナ。
  2. SearchBar(青)はユーザ入力を受け取る。
  3. ProductTable(紫)はユーザ入力に従ってリストを表示およびフィルタリングする。
  4. ProductCategoryRow(緑)はカテゴリごとの見出しを表示する。
  5. ProductRow(黄)は個々の製品に対応する行を表示する。

※1 つのコンポーネントは理想的には 1 つのことだけを行うべき

2. 静的なバージョンを作成する

  • わかりやすいアプローチ
    単にデータモデルから UI をレンダーするバージョンを作成
    ┗ ざっくり、全体像をつくてしまう。
  • データモデルをレンダーするアプリ作成時は、props経由でデータを渡す。
    ┗ 静的バージョンでstateは使わない。
  • 初心者なのでトップダウンでコンポーネントを構築してゆく
$ cd src 
$ ls -1
App.css
App.jsx
assets/
index.css
main.jsx

App.jsx

import './App.css'
function App() {

}
export default App
  • 箱全体を出力 products にjsonを渡す
export default function App() {
  return <FilterableProductTable products={PRODUCTS} />;
}

  • 箱の中身、SearchBarとProductTableを読み込みprops でProductTableにjsonデータをそのまま渡す
function FilterableProductTable({ products }) {
  return (
    <div>
      <SearchBar />
      <ProductTable products={products} />
    </div>
  );
}

  • 検索部分のフォーム
function SearchBar() {
  return (
    <form>
      <input type="text" placeholder="Search..." />
      <label>
        <input type="checkbox" />
        {' '}
        Only show products in stock
      </label>
    </form>
  );
}
  • ここでjson を展開し、ProductCategoryRow ProductRow を読み込む、
    {rows}では、値をもらったProductCategoryRow と ProductRow が展開される。
function ProductTable({ products }) {
  const rows = [];
  let lastCategory = null;

  products.forEach((product) => {
    if (product.category !== lastCategory) {
      rows.push(
        <ProductCategoryRow
          category={product.category}
          key={product.category} />
      );
    }
    rows.push(
      <ProductRow
        product={product}
        key={product.name} />
    );
    lastCategory = product.category;
  });

  return (
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>{rows}</tbody>
    </table>
  );
}
  • {rows}の展開イメージがつかなかったので、入っているもの書き出したら腑に落ちた
//{rows}以下が連解される
//	<ProductCategoryRow category={product.category} key={product.category} />
//	<ProductRow product={product} key={product.name} />
//	<ProductRow product={product} key={product.name} />
//	<ProductRow product={product} key={product.name} />
//	<ProductCategoryRow category={product.category} key={product.category} />
//	<ProductRow product={product} key={product.name} />
//	<ProductRow product={product} key={product.name} />
//	<ProductRow product={product} key={product.name} />
  • trtd要素の出力。
function ProductRow({ product }) {
  const name = product.stocked ? product.name :
    <span style={{ color: 'red' }}>
      {product.name}
    </span>;

  return (
    <tr>
      <td>{name}</td>
      <td>{product.price}</td>
    </tr>
  );
}

function ProductCategoryRow({ category }) {
  return (
    <tr>
      <th colSpan="2">
        {category}
      </th>
    </tr>
  );
}

気づき

コンポーネントの階層に分割はあらかじめデザインの時点でどうするか決めておくのがよさそうなのがなんとなくわかった。

次やること

ステップ 3:UI の状態を最小限かつ完全に表現する方法を見つける

試すこと

外部のJSONから読み込んで同じものを表示させてみる
参照:https://devsakaso.com/react-get-json-external-api/
参照:https://super-yusuke.gitbook.io/udemy-course/fei-tong-qi-chu-li-promise-ajax/json-woshisonoworendaringusuru-react-app-no

Discussion