業務でReactを書くためのハンズオン(toC Web向け)

事前準備

今回、既存のAPI(GraphQL)を使ったページを作るので、以下ブランチに切り替えをお願いします。
npm install

LIPSのフロントエンドについて

知ってる人が多いかもだけどとりあえずこんな感じ
  • LIPS (toC)
    • 主にRailsのtemplate
    • (これから書くときはjQuery使わないようにね。。。)
  • LIPS Web
    • 新しい画面の一部はこちら
    • PC診断・肌診断…
    • Next.jsで実装されてます
    • 今日扱うのはこれ
  • LIPS Shopping
    • ショッピング向けの商品一覧・検索画面
    • Next.jsで実装されてます
  • SaaS (for Brands)
    • ほぼReact(SPA)
    • あんまり触る人は少ないかも(僕とかkawamitsuさんとか)
  • Admin
    • Railsのテンプレートが多いが新しいものはReact(SPA)で書かれている
    • (なんか大昔のHackdayでハンズオンしたような)

早速作ってみる

今回は単純に商品一覧を表示する画面を作っていきます。
以下ブランチを利用します
 

ページを実装する

frontend/web/src/pages内にエントリポイントファイル(tsx)をおくと、Next.jsが勝手にルーティングしてくれます。
例えば、今回、`/products/lists`にホスティングしたいなら
内に`lists.page.tsx`を配置して以下のように書いてみてください
もし、stagingでだけ(本番では出したくない)場合は、
ファイル名を`frontend/web/src/pages/products/lists.previewpage.tsx`にするとページにアクセスできなくなります。
しかし、以下のenvを追加するとページにアクセスできるようになります。

コンポーネントを実装する

Reactのコンポーネントを実装します。
今回、商品を一覧で表示したいので商品のセル(カード)が必要なのですが、すでに実装されてます。
Storybookを開いてみましょう。以下コマンドで開くことができます。
Storybookを軽く説明すると、
  • コンポーネントを単体で開発できる(ページとかに置かずとも画面に描画できる)
    • 実装効率はこちらの方が高い
  • コンポーネントのカタログになる
    • いろいろなパラメータをUI上で簡単に変更してUIを確認できる
    • いろんな機能(Viewport変更)等でコンポーネントの確認がよりやりやすい
    • chromatic(外部サイト)とかにもホスティングできて、デザイナへの共有もやりやすい
のでコンポーネントを作る際は基本的にStorybookのファイルも作成してください(大事)
Product>ProductCellに実装されています。

とりあえず商品を引っ張ってこれるようにしておく

基本的にAPI Callは昔懐かしいrestではなく、GraphQLで引っ張ってきます。
localでRailsを実行していると、graphiqlが動いているので、
http://localhost:3000/graphiqlにアクセスして下記queryを実行してみましょう。
ちゃんと実行できていたら、frontend/web/src/graphql内に、productsOnHandson.graphqlとしてクエリを保存し、以下コマンドを実行してください
graphqlの情報から必要な型情報、hooks等が生成されます。
続いて、先ほど書いたを以下のように編集してみましょう
LIPS/Webではapi callにurqlを使っています。
諸々の設定は今回省略しますが、今回、主に以下がパフォーマンス的に重要になるかと思います。
  1. cacheExchange
    1. queryとvariable(apiパラメータ)のセットでキャッシュしてくれる
    1. これを有効化すると子供コンポーネントでのapi callがいい感じにSSR化される
続いて、実際に画面に商品を表示してみましょう
src/components/standalones/Product配下にProcductListPage.tsxを作成してください
useProductsOnHandsonQueryは、先ほどのnpm run gen:webで生成されたcustom hookです。これを元にAPI callを行っています。
今回はSSRを有効化しているので初回表示時はSSR、つまりサーバー側でAPI callが行われます。
先ほどのssrをfalseにすると、Client側で実行されます。
このデータを元にいい感じに整形してproductsに保存、そいつをProductCellに渡して表示してます。

無限ローディングをやってみる

本来だと無限スクロールは自分で実装(DOMの要素が下までスクロールされているかチェックする)とかしないといけないですが、便利なライブラリでそこら辺は簡略化できます。
今回はpagingではなくてoffsetでデータを追加取得する戦略で実装しています。
Reactのhooksに慣れ親しんだ方ならわかるかと思いますが、
  1. スクロールしてが呼ばれる
  1. が呼ばれて、fetchの最中でなければoffsetを増やす()
  1. 副作用により再レンダリングされる
  1. 内のoffsetが変更されていて、そちらをhookにfetchが走る
という流れです。
 
 
 

おまけ

ページが公開されていない

おそらくnginx側の設定ができてないので、追加してあげる必要がある
(Railsだけでもapi.lipscosme.comにしたい)

認証まわりをアレしたい

Rails側でいい感じにRedirectしてあげないとダメらしい
(認証だけでもマイクロサービスに切り出せるといいなぁ)

更新(mutation)をしたい