AppBrewフロントエンド学院~Reactを書いてみよう~

概要

最低限、Reactをかけるようになる
  • Componentを作ってみる
    • Componentって
    • 実際に書く
  • 動きをつける
    • hooksについて
      • useState
      • useEffect
      • hooksのルール
    • 実際にstateを作ってみる
  • Todoアプリを作る
    • 完成形
    • 一覧で表示できるようにする
      • keyについて
    • Form部分を作る
  • 発展(時間が余れば)
    • web apiを呼んでみよう
    • axios、useSWRを使ったapi通信

必要なもの

GitHubアカウント

前もって見ていると嬉しいもの

本題

そもそもReactってなんやねん?

  • Facebookが2013年ごろから公開しているUI構築のためのJavaScriptライブラリ
    • フレームワークではない
    • そのため、他のフレームワーク(Angular、Vue)と違って画面の描画に特化している
  • 今までのjsとかjQueryと違ってメモリ上でUIの状態等を保存し(fiber)、DOMと同期している(仮想DOM)
    • とはいえ最近のトレンドは脱仮想DOMだったりする
      • Svelte、SolidJSとか
  • 最近はパフォーマンス向上のためにサーバー側でのレンダリング等かなり際どいこともやり始めてる(Next.js)

Componentを作ってみる

ここからはcodesandboxのコードを使っていきます

Componentとは?

雑にいうとパーツ。UIを構築する1要素
  • ボタン
  • フォーム
  • ヘッダー
ReactではこのComponentを定義し、組み合わせて画面を作っていく

実際に書く

  • なんかHTMLみたいなのが混ざっているけどこんなふうにかく(JSX)
  • 基本的にComponentは関数として定義する
    • 引数(後述。propsという)を受け取ってUI(HTML)を返す
  • 古い記事やライブラリだと、class componentと言われるスタイルで書かれていることも…
    • これは今回無視でいいです。(AndroidのプロジェクトみたらKotlinじゃなくてJavaでした、に近い)
  • propsがこのcomponentの引数のようなもの
    • 「UIは何かしらの状態(props)の写像(なんすか、しゃぞーって)」という思想の表れでもある(大事)
  • HTML内で変数等を参照する場合はと書く(そうしないと文字として認識されます)
  • propsのなかにobjectの形でparamが突っ込まれる

動きをつける

Reactでは画面にインタラクション(クリックしたら値が変わるとか生JSとかjQueryで辛かったあれ)が簡単にできます
ただ、これでは動きません。
可変な状態を作るにはuseStateというhooksを使う必要があります。

hooksについて

フックの導入 - React
フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。 この useState という関数が、これから説明する最初のフック (Hook) です。これは単なるチラ見せですので、まだ意味が分からなくても問題ありません! 次のページからフックについて学び始めることができます。このページの残りの部分では、我々がなぜ React にフックの仕組みを加えることにしたのか、そして素晴らしいアプリケーションを作るためにどのように便利なのかについて説明していきます。 補足 React 16.8.0 がフックをサポートする最初のバージョンです。アップグレードの際は、React DOM を含むすべてのパッケージの更新を忘れないようにしてください。React Native は React Native 0.59 リリース 以降でフックをサポートします。 React Conf 2018 にて Sophie Alpert と Dan Abramov がフックについての発表を行い、続いて Ryan Florence がアプリケーションでフックを使うようにリファクタリングする方法についてのデモを行いました。ビデオは以下で見ることができます: 先に進む前に注意すべきこととして、フックは: 完全にオプトインです。既存のコードを書き換えずに一部のコンポーネントでフックを試すことができます。またやりたくないのであれば、今すぐに学んだり使ったりする必要もありません。 100% 後方互換です。フックには破壊的な変更は一切含まれていません。 今すぐ利用可能です。フックは v16.8.0 のリリースから利用可能です。 React からクラス型コンポーネントを削除する予定はありません。このページの 下部 で段階的にフックを採用していく方法について読むことができます。 フックは既にあなたが知っている React のコンセプトを置き換えるものではありません。 むしろ、フックはあなたが既に知っている props、state、コンテクスト、ref、ライフサイクルといったコンセプトに対してより直接的な API を提供するものです。後でお見せするように、フックによって、これらを組み合わせるパワフルな手段も得ることができます。 とにかくフックを学び始めたいという方は、どうぞ直接次のページに進んでください! 以下には、なぜ React にフックを導入することにしたのか、アプリケーションを書き換えずにどのようにしてフックを使い始めることができるのかについて解説しています。 フックによって、過去 5 年で何万というコンポーネントを作成・メンテナンスする中で我々が遭遇してきた、一見互いにあまり関係なさそうに見える様々な問題が解決されます。あなたが React を学習中の場合でも、毎日使っている場合でも、似たようなコンポーネントモデルを持つ別のライブラリが好きな場合でも、これらの問題の幾つかを認識しているかもしれません。 React は再利用可能な振る舞いをコンポーネントに「付加する」方法(例えばストアオブジェクトを connect するなど)を提供していません。React をしばらく使った事があれば、この問題を解決するための レンダープロップや 高階コンポーネントといったパターンをご存じかもしれません。しかしこれらのパターンを使おうとするとコンポーネントの再構成が必要であり、面倒なうえにコードを追うのが難しくなります。典型的な React アプリを React DevTools で見てみると、おそらくプロバイダやらコンシューマやら高階コンポーネントやらレンダープロップやら、その他諸々の抽象化が多層に積み重なった『ラッパー地獄』を見ることになるでしょう。 DevTools でそれらをフィルタして隠す ことはできますが、この背景にはもっと根本的な問題があるということがわかります:React にはステートフルなロジックを共有するためのよりよい基本機能が必要なのです。 フックを使えば、ステートを持ったロジックをコンポーネントから抽出して、単独でテストしたり、また再利用したりすることができます。 フックを使えば、ステートを持ったロジックを、コンポーネントの階層構造を変えることなしに再利用できるのです。 このため、多数のコンポーネント間で、あるいはコミュニティ全体で、フックを共有することが簡単になります。 この点については 独自フックの作成 にてより詳しく述べていきます。 我々はよく、最初はシンプルだったのに、state ...
↑詳細な説明は上に載っているが、
State(状態)を持ったロジックを再利用可能な関数にすることができる
が大きなモチベーションだったりする
これによって
  • どこでもよく使うような処理(modalのon/off)を共通化
  • APIの呼び出し(ローディング、エラーハンドリング、表示)をhooksで隠蔽してUIに提供
  • クエリパラメータの値やその変更等を関数化してReactから利用しやすい形で提供
など様々できる

実際にstateを作ってみる

という形でstate(状態を定義できる)
さっきのアプリはこのようになる

useEffect

データの取得だったりDOM操作などのレンダリング中に行えない動作をreactでは副作用というがこれらを実現可能にするのがuseEffect
こうしてあげることでレンダリングごとに実行される。(が、ここらへん、最新のReactだとややこしい話があります)
ただ、再レンダリングされるたびに呼び出される必要がなかったりする
  • 値が変更された時だけ評価してほしい
    • apiのparamが変わったとか
  • マウント(雑にいうとコンポーネントが表示される直前)にだけ実行したい
ということの方が多いので、そういう場合は第二引数に配列を用意
 
クリーンアップが有用になるのは以下のようなケースとか
 
クリーンアップしなくて良いときは値を返さない。

hooksのルール

フックのルール - React
フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。 フックは JavaScript の関数ですが、それらを使う際には以下の 2 つのルールに従う必要があります。我々は自動的にこのルールを強制するための linter プラグイン を提供しています。 フックをループや条件分岐、あるいはネストされた関数内で呼び出してはいけません。代わりに、あなたの React の関数のトップレベルでのみ、あらゆる早期 return 文よりも前の場所で呼び出してください。これを守ることで、コンポーネントがレンダーされる際に毎回同じ順番で呼び出されるということが保証されます。これが、複数回 useState や useEffect が呼び出された場合でも React がフックの状態を正しく保持するための仕組みです(興味がある場合は ページ下部 で詳しく説明しています)。 フックを通常の JavaScript 関数から呼び出さないでください。 代わりに以下のようにします。 ✅ React の関数コンポーネント内から呼び出す。 ✅ カスタムフック内(次のページで説明します)から呼び出す。 このルールを守ることで、コンポーネント内のすべての state を使うロジックがソースコードから間違いなく参照可能になります。 これらの 2 つのルールを強制できる eslint-plugin-react-hooks という ESLint のプラグインをリリースしました。試したい場合はあなたのプロジェクトに以下のようにして加えることができます。 このプラグインは
こんないろんなことができそうなhooksですが、色々とルールがあります
  • React componentの中でしか使えない
    • そのため、カスタムhook含めて、componentからしか呼べません
  • トップレベルで使う
    • なので、条件分岐とかより前に書く必要があります

Todoアプリを作る

今回はこのようなアプリを実装してみます
コンポーネントとしてはこのように作ると綺麗にできます
Todoコンポーネント自体が親コンポーネントとなっていて、タスクの一覧を保持し、追加などの管理も行なっています。
それでは、インタラクションが絡まないTodoListから作っていきましょう

一覧で表示できるようにする

Todoがタスクリストを保持しているので、子要素であるTodoListコンポーネント側では、親の持つタスクリストを受け取るようにして表示します。
 
これで親からデータが渡ってきたので表示部分を実装します。
jsにはmap関数(rubyと同じ)があるので、それを使ってあげます。内ではHTMLテンプレート内でもjsのコードが書けます
ただ、このように書くと、表示はされますが、開発者ツールでこのようなエラーが出るかと思います。
そうです、mapなどで同じ要素を動的に生成した際にはkey attributeを仕込む必要があります。Reactはこれをもとに要素の更新や追加、削除を行います。
ここで大事なのは
keyが一意であること
です。これを間違えると、正しく表示されないなどの不具合が出てきます。
特にこのようなシンプルな例では起こり得ないですが、APIなど、要素が複雑かつ多くなる場合、表示がおかしくなる可能性があります。

Form部分を作る

見た目としてはinputとボタンを用意します。
Reactのstateの値はreadonlyなので、このままだと値の変更がされません。
そのため、inputタグの変更に合わせてvalueの値が変わるように実装します
これで、値を自由に書き換えられるようになりました。

実際に動くように仕上げる

最後に、具体的にタスクの追加等のロジックを作りましょう。