## RailsとReactでUberEats風SPAアプリケーションをつくってみよう! # 峯岸 6-4 ### 自分の環境 Homebrew 3.2.9 ruby 2.6.6 Bundler 2.2.16 Yarn 1.22.10 Rails 6.1.4 node v14.15.0 ## Tips ターミナルをカスタマイズ https://hyper.is/ PATHを通すとは? (Mac OS X) https://qiita.com/soarflat/items/09be6ab9cd91d366bf71 ウェブ向けの機能はReact本体ではなく、そこから派生したreact-domが担当しています。 **コンパイル時のエラーはターミナルに出力される** スクリプトの実行中のエラーはターミナルには表示されずにブラウザ上に表示される。 検証ツールの使い方 https://developer.chrome.com/docs/devtools/console/ - ページ遷移は全てReact Routerをつかったルーティング - RailsではViewを用意せず、React側で画面を作っていく >一般的にデータベースに作成されたレコードは論理削除(booleanなどで活性 -> 非活性に変更すること)できる設計が多いです。例えばSNSのユーザーデータなどを考えても、退会したら削除するのではなく、論理削除できるようにすることで、退会したユーザーがどんな情報を持っていたか?を追えるようになります。 - Reactの組み込みAPIであるReact Hooksではシンプルにデータを保持することができる - コンポーネントの中に複雑なロジックやAPIを呼ぶ関数などを定義せず、外のモジュールに書き出す - 4-6がフロントとバックの繋ぎこみの部分なので重要な章 - **バックエンドとフロントをつなぐ重要な役割がコントローラー(3-1)** - SPAの文脈ではこのControllerのことをAPIと呼ぶらしい。データを取得する接点と考えても良い。 - データ(間)の整合性が求められる場合にトランザクションを使います。 - 複数のコンポーネント、関数、モジュールから参照される値は別ファイルに定義しておくことをオススメします。 - AxiosとReactRouterとCORSの設定がめちゃ重要 - **styled-componentは必ずコンポーネントの外で定義する** - HTMLタグにスタイルを当てる場合は `style.tag_name` - コンポーネントにスタイルを当てる場合は`style(Component_name)` ## 参照 今から始めるReact入門 〜 React Router https://qiita.com/TsutomuNakamura/items/34a7339a05bb5fd697f2 ReactJS Tutorial - 5 - Functional Components https://www.youtube.com/watch?v=Cla1WwguArA ドメイン駆動設計は何を解決しようとしているのか[DDD] https://qiita.com/little_hand_s/items/721afcbc555444663247 ## あとで調べる - scopeの書き方が曖昧 ```ruby= scope :other_restaurant, -> (picked_restaurant_id) { where.not(restaurant_id: picked_restaurant_id) } ``` - line_foodインスタンスがもつfoodの金額? - order: selfって何してるんだっけ(2-2)  - シェル芸 ```ruby= def total_price(posted_line_foods) posted_line_foods.sum{|line_food|line_food.total_amount } + posted_line_foods.first.restaurant.fee end ``` Function Component?? >本教材ではFunction Componentでコンポーネントを定義していきます。Class Componentに比べて見通しが良いこと、またReact Hooksの登場以降こちらがベーシックになりつつあることなどを考慮した結果です。 > - Fragmentとは - axiosについて - render??  --- --- --- # 肉 ### 8/28(土)初日 14:20 2章 2-1  15:20 2章 2-3 ### コントローラーを作る `module Api`とすることで、名前空間を指定している `api/v1/ディレクトリ` apiの下の、v1の下の、class RestaurantsController <br> ```ruby= render json: { restaurants: restaurants }, status: :ok # リクエストが成功したこと、200 OKと一緒にデータを返す ``` 17:50 3章 3-4 #### 仮注文のコントローラー - `.exists?` メソッドは対象のインスタンスのデータがDBに存在するかどうか?をtrue/falseで返すメソッド - `line_foods = LineFood.active` models/line_food.rbのscopeを使っている(モデル名.スコープ名)で使える - Rubyの`.map`メソッドは配列やハッシュオブジェクトなどを1つずつとりだし、`.map`より後ろのブロックにあてていくスタイル🚗 - 保守性の観点でなるべくデータの計算などはサーバーサイドで担当すべき #### `replace`アクションを作る 理由として、既にある古い仮注文を論理削除し(activeというカラムにfalseを入れるなどして、データを非活性の状態にする)新しいレコードを作成する 0:20 3章 3-6 #### トランザクション - AとBの間で起こる処理の処理のどちらか**片方でも失敗したらロールバックする** モデル内で定義したメソッドの中に`ActiveRecord::Base.transaction`を記入し更にトランザクションの処理を書いていく 0:27 3章 3-7 **テストはなるべく書こうね❤︎** ### 4章 4-1 #### CRA - `localhost:3000`と`localhost:3001`の2つのサーバーを立ち上げる事でフロントエンドとサーバーサイドが疎通することができる - このアプリのディレクトリに居ることを確認し `npx create-react-app frontend`コマンドでフロント側を生成 - flontendディレクトリに移動し、今回は`npm start`でサーバー起動した(元太状態🍙 🐍) - りあクト!でプラグインを入れている場合、画像のように表示が出るかも(Allowを押した)  0:58 4-2 #### React Routerを導入 `npm install react-router-dom` - containersディレクトリ作成→中にRestaurants.jsx、Foods.jsx、Orders.jsxの3つのファイルを作成(コンポーネント) - ↑の3つのコンポーネントを`App.js`でimportし、React Routerでルーティングさせる - `<Router>...</Router>`で全体を囲む - ルーティング先のコンポーネントを`<Switch>...</Switch>`で囲む - ページ共通のヘッダーやフッターがある場合には`<Switch>...</Switch>`の外に出しておく --- - <a href="https://ja.reactjs.org/docs/fragments.html">フラグメント(fragment)</a> Fragmentを書くことでdivタグを省略できる 書かずに`<div>`タグ2つ書くとエラー `<>と</>`でFragmentの記述を省略できる `import React, { Fragment } from 'react';` --- - <a href="https://ja.reactjs.org/docs/components-and-props.html">props</a> - コンポーネントの属性、一度設定してしまえば後から変更ができない - `exact`について<a href="https://qiita.com/gombeedoe/items/6f4ea0e37775bac01c0d">qiitaの記事</a> --- #### <a href="https://reactrouter.com/web/api/match">`match`オブジェクト</a> **matchの中には`path`・`url`・`params`・`isExact`などの情報が入っている** --- - パラメーターとして設定したい部分は`:paramsName`と`:`を付ける 今回で言うと `path="/restaurants/:restaurantsId/foods"`の`:restaurantsId`部分 ## 寝落ち 4:04 -実装した結果から手前 9:27 - 「SPAだから早い」というのは常にtrueではない - SEOに弱い 14:10 4-5 - axiosを導入する(`$ npm install axios`) - axiosは<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>ベースで非同期処理を実装できる。更にthen()によって成功した場合と失敗した場合のコールバック関数を取ります - `console.error(e)`の`(e)`は何でもいいが分かりやすくしよう。hogeでもfでもiでも良い -- <a href ="https://ja.reactjs.org/docs/handling-events.html">イベント処理</a> - `useEffect`は**React Hooks**の一つ **`gem 'rack-cors'`** のお陰で通信の許可を設定できる ### 5章 8/29 21:50 `console.log()`で表示したデータをコンポーネントが受け取って表示するまで --- --- #### jsx React要素を生成するためReactで使われるjsの拡張言語 - return の中がjsx構文 - class は className と書く - 基本的にHTMLっぽいjsで書ける - キャメルケースで記述 - {}内で変数を使える - 閉じタグ必要 `/>` - jsxは必ず階層構造(最上位コンポーネントは並列に出来ない) いきなり`<p>ほげ</p>`タグの様に並べて記述するとエラーになるので`<div>`タグなり書かないといけない`<React.Fragment>`もしくは`<></>`の空タグ --- --- ### Hooksとは **Classコンポーネント**の中でしか使えなかった機能が、**関数コンポーネント**でも使えるようになった(2020年2月から) どんな機能かというと↓ - **state** コンポーネント利用時に設定ができる値で、コンポーネントの中で状態を管理するがpropsと違い後から変更ができる - **ライフサイクル** コンポーネントの時間の流れに基づいているメソッド このHooksの登場によって **"classコンポーネントでしか出来ないことが無くなった"** ので関数コンポーネントを使う割合が多くなった。 一言で: Hooksを使うことで関数コンポーネントでもclassコンポーネントの機能に接続しますよ〜 ### state を使う理由 - ❌ DOMでコンポーネント内の要素を書き換えてはならない(getElementとか禁止) - ⭕️ 新しい値を使ってレンダリングさせる - レンダリングするタイミングはstateが変更された時 - 親から渡ってきたpropsが変更された時 ### useStateメソッドによるstateの宣言 ```javascript= const [hungry, setState] = useState(hoge) // 現在の状態↑ を, ↑更新するための関数 ↑初期値 // 上の[]の名前はなんでもいいよお useStateを使うとstateとsetStateが返ってくるよ ``` お腹が空いた状態(hungry)に初期値(hoge)が入っていて ```javascript= setState(food) //↑更新関数に↑(新しい値)を渡すことでstateが更新される ``` 更新関数(setState)に食べ物(food)を渡したら更新される ### propsとstateの違い どっちもレンダリングするきっかけにはなる - props - 親コンポーネントから子コンポーネントに受け渡された値がprops - 逆に子から親にpropsを更新というのは出来ない - state - コンポーネントの中で作られ、制御される値がstate --- --- ### 気になる点 - なぜわざわざマイグレーションファイルを手作りしてtouchコマンドでmodelファイルを作る必要があるのか。`rails g model` で良くね? 2-2 (4) ```ruby= ActiveRecord::Base.transaction do #このトランザクションって何だっけ line_foods.each do |line_food| line_food.update_attributes!(active: false, order: self) end self.save! end ``` - ↑の中のself って何だっけ --- - v1というURL = APIのバージョン(APIを更新する場合にスイッチングしやすくするため)今回は分かりやすくするためにURLに書いている - <a href="https://qiita.com/t_nakayama0714/items/bfe4852e0535858ee662#:~:text=%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8%20%E3%81%A8%E3%81%AF%E3%80%81%E4%B8%BB,%E4%BA%BA%E7%89%A9%E3%82%92%20%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8%E4%BA%BA%20%E3%81%A8%E3%81%84%E3%81%86%E3%80%82">シェル芸🐚</a> - line_foodインスタンスを生成する🤔 4-1 `npm start`でもいいけど`yarn start`でもいいのでは?🤔 4-2 **React Hooks** ってなんだ?🤔 **function component**ってなんだ?🤔 4-6 **useEffect**ってなんだ?🤔 ***ライフサイクルメソッド*** ...ってscopeの範囲が変わる? DOMに挿入された時のscope。 コンポーネントが更新された時のscope。 コンポーネントがDOMからアンマウント(削除)された時scope。 ***配列***と***関数***と***オブジェクト***は最低限知っておけ! ***fetch***はjsのAPI ### ルーティングはきちんと合わせよう!  --- --- --- # 三浦(熱さまシート最強) ### 進捗 4章終了 ## 1章 **論理削除** boolean型で活性/非活性を切り替えることで、見た目上は削除できているが、DBにはデータが残っている状態。退会ユーザー等は論理削除とすることで、退会後でもユーザーが持っていたデータを取得することができる。 →専用のカラムを追加することで実装できる。 **物理削除** DB上からもデータを削除するため、復元不可。 ## 2章 **optional: true** railsのアソシエーションで使用できるオプションで、外部キーカラムのnilを許容することができる。 外部キーのカラムはデフォルトでnilを弾く。 例)`belongs_to :order, optional: true` ## 3章 mapは最終的に配列を返す。 eachはただ繰り返し処理を行うだけで、そのままでは配列は返さない。 ## 4章 npm install react-router-dom ## 5章 setState render内でstateを変更すると、変更されたタイミングでrender(再描画)されるので、無限renderが発生する。 そこで、renderをさせずに値を変更するためにsetStateを使用している。 ### 疑問点 ・exits present anyの使い分けの理解が怪しい ・2-2 order.rb oerder: selfとは ```ruby= posted_line_foods = LineFood.where(id: params[:line_food_ids]) order = Order.new( total_price: total_price(posted_line_foods), ) ``` ・3-1 restaurants_controller.rbの記述 2回ネストしてclassを定義してるのはなに? ・3-3 line_foods_controller.rb status: :created status: :internal_server_error ここらへん意味ぷ statusってすでに存在してるものから選択してるんよね? https://www.itmanage.co.jp/column/http-www-request-response-statuscode/ ・3-4 line_foods_controller.rb 全体的にjsonの書き方がわからん
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up