Reactを1年以上学んできて、今振り返ってみると躓いてしまっていたところ、難しかったところがたくさんありました。
本記事は、これからReactを学ぶ上でまず初めに心がけておかないといけないことについて書いていきます。
本記事の内容が誤っていることも十二分に想定されるため、有識者のマサカリを歓迎しています。
本記事の中の一部でもいいので、初心者の助けになれば幸いです。
一言でいうと
- Reactはコンポーネントという単位でUIを管理する!
- 状態という概念は、ユーザーの行動を画面に反映させるため使われる、とても大事な概念!
- Reactはフロントエンドとバックエンドの融合体!
- webページの設計は、汎用的な設計が合わないこともある!
- Reactを活用するためのライブラリについても必要に応じて学ぼう!
- Javascript/Typescript特有の表現に負けないよう頑張ろう!
本記事の対象
以下のような人を想定して書いてます。いずれも初学者向けです。
- Reactについて学んでみたけど、なんか独特でわかりづらい
- そろそろフロントエンドを触ってみたいが、何となくハードルが高い
- いろいろプログラミングについて勉強してみたけど、フロントエンドは独特で難しいと感じる
自己紹介
- FE経験2年ほどの新人Reactエンジニア
- 主にtypescript × Reactでのコーディングを担当
出来ること
- hooksを用いた状態管理(簡単な奴)
- レンダリングの意識。簡単なリポジトリパターンのデザイン
- ちょっとしたapiサービスを用いた画面構成
改めてReactについておさらいしよう
React公式のlearnページでは、Reactを以下のように説明しています。
React は、ユーザインターフェース(UI)を表示するための JavaScript ライブラリです。UI はボタンやテキスト、画像といった小さな要素から構成されています。React ではこれらを、ネストして再利用できるコンポーネントにまとめることができます。ウェブサイトであれ携帯電話アプリであれ、画面上のすべてのものはコンポーネントに分解することができます。
3行にまとめると
- ReactはUIを作るためのライブラリだよ
- UIをコンポーネントっていう小っちゃい部品に分割するよ
- 画面上のモノは全てコンポーネントだよ
となります。
Reactでは、「コンポーネント」という単位で、いろいろなものを管理する、ということだけ覚えておいてください。
避けては通れない「状態」という概念
Reactの中でもトップクラスに重要なのに、何か抽象的な概念である「状態」ですが、これを理解することが、React学習の第一歩になります。
そもそも「状態(state)」とは?
Reactにおける 「状態(state)」 とは、
「ユーザーの操作によって変化し、それに応じて画面の表示も変わるデータ」 のことです。
例として、よくあるネットショップを考えてみましょう
あなたはあるネットショップで、充電ケーブルを買うことにしました。
充電ケーブルの商品ページに移動したら、その充電ケーブルは
- 「長さ」
- 「色」
- 「本数」
を選択することが出来ます。
あなたは「白い」「1mの」ケーブルを選択し、「2本」カートに入れました。
別のユーザーは「赤い」「0.5m」のケーブルを「1本」買うかもしれません。
このように、ユーザーごとに異なるデータを管理するための仕組みが「状態」 です。
Reactでは、この「状態」をうまく管理することで、動的に画面を更新し、ユーザーの操作に対応する画面を作り上げます。
こういうイメージ。もとは空っぽで、ユーザの変更に応じてここの値が更新される。
「状態」がなかったらどうなる?
もし「状態」という概念がなかったら、
画面に表示された選択肢を変更しても、リロードしないと反映されない という悲惨な状況になります。
例えば、次のような単純なHTMLを考えてみてください。
<select>
<option>白</option>
<option>赤</option>
</select>
<p>選んだ色: 白</p>
このコードでは、選択肢を変えても「選んだ色」はずっと「白」のままです。
なぜなら、赤を選んだという情報を伝えることが出来ないからです。
この問題を回避できるという点で、Reactの「状態(state)」は非常に重要なのです。
(ちなみに、選んだ色:白みたいな、値を直接書き込むものをハードコーディングっていいます。大体の場合でよくないとされているからやめましょう!)
Reactは「フロントエンド」だけのライブラリじゃない
React学習がめちゃくちゃ大変だった理由の一つです。
まず、「フロントエンド」という言葉について改めて確認してみましょう(wikipediaより引用)
ソフトウェア設計におけるフロントエンドは、ユーザーと直接やりとりするソフトウェアシステムの部分を指し、バックエンドはフロントエンドへの出力を生成する部分を指す。
つまり、ユーザーが直接触るボタンや入力フォームなどを整える領域を指します。
今回はこの定義に則って話を進めます。
Reactは「ユーザーの動きが反映されるwebページを作るためのJavascriptライブラリ」です。
そのため、多くの人はReactを「フロントエンドのライブラリ・技術」という風に分類しているかと思います。
ただ、Reactは「フロントエンド」という範疇を大きく超えた実装を要求されるライブラリでもあります。
たとえば、本当によくあるチュートリアルで作られるボタンを考える場合、こんな感じに実装されるものかと思います。
(まずわけがわからないと思うので読み飛ばしてください。実装編で解説します)
import { useState } from "react"
export const UseStateSample:FC = () => {
//実装編で詳しく説明します
const [count,setCount] = useState(0)
const countHandler = () => {
setCount(prev => prev + 1)
}
return (
<button onClick={countHandler}> click count: {count} </button>
)
}
上記のコードは「クリックするとcountという数値が増えるというコードです
よくあるやつですね。
さて、このボタンにはいくつかの機能が存在します。
- ボタンの枠とclick countを表示する(当たり前ですけど)
- クリックされたかどうかを監視する
- クリックされた回数をカウントする
このうち、先ほどの「フロントエンドの定義」に相当するのは1.または2.ですね?
3.については
バックエンドはフロントエンドへの出力を生成する部分を指す。
のバックエンドの処理に当たります。フロントが表示しているclick countを準備しているからですね。
そして、Reactを使う最大の利点はこの「ユーザーの操作に対して、動的に表示を変える機能を実装できる」という点に尽きます。
即ち、Reactにて画面を実装するためには
- 適切な表示を行うフロントエンドの領域
- フロントエンドが表示する情報を提供するバックエンドの領域
この二つを同時に実装する必要があるのです。
これが、次の章の混乱にもつながってきます
「お勉強」が通用しないことがある
プログラミングを学ぶ際、多くの方が 「設計」 についての知識を身につけようとするかと思います。
MVC、DDD、レイヤードアーキテクチャ……
こうした設計パターンを学ぶことで、「コードの責務を適切に分けることが重要だ」と考えるようになるでしょう。
しかし、Reactではこの"常識"が通用しない場面に多々遭遇します。
むしろ 「勉強した通りにやろうとすると、逆にハマる」 ことが多いのです。
Reactは「触ると何かが起こる」ものを作る技術
Reactは「フロントエンドのライブラリ」と言われますが、実態としては
「ユーザーの操作に応じて、画面が動的に変化する」仕組みを作るためのツールです。
例えば、ボタンを作成する際には、次のような処理が必要になります。
- ボタンの見た目を表示する(View)
- クリックされた際の処理を実行する(Controller)
- 必要に応じてデータをサーバーへ送信する(Model)
一般的な設計の考え方では、「View」「Controller」「Model」は明確に分けるべきとされています。
しかし、Reactでは これらを同じコンポーネントの中で扱うことが一般的です。
なぜなら、コンポーネント単位で「状態」と「UI」を結びつけることが、Reactの設計思想だからです。
MVCのような厳密な分類よりも、「どのコンポーネントがどのデータを管理するか?」を考える方が重要になります。
先ほど挙げた「クリックした回数を表示するボタン」を例にすると
1つのコンポーネントの中に
- ボタンの見た目(View)
- クリックの処理(Controller)
- カウントの状態管理(Model)
がすべて含まれています。
「このように1つのファイルに詰め込んでしまって大丈夫なのか?」と疑問に思うかもしれません。
しかし、Reactではむしろこの形が自然であり、分けるとかえって扱いづらくなることが多い のです。
Reactの設計に慣れるためには、
「まずはReactの流儀1に乗っかってみる」 ことが重要です。
MVCのような既存の設計パターンにこだわるのではなく、
「この状態はどこで管理すべきか?」 という視点を持つことで、
Reactの考え方が理解しやすくなると思います。
ReactはReactだけではほぼ完結しない
残念ながら、Reactを用いたWebページの実装がReactのみで完結することはほぼありません。
Reactを用いた開発には、お供となるライブラリやフレームワークがたくさん登場します。
Next.js,Nest.js,Jotai,Zustand,Redux,TailwindCSS,その他もろもろ……
実際の開発において、Reactだけ知っていればなんとかなる、というケースはほとんどありません。
なぜなら、先述した状態管理の複雑さや、フロントエンドとバックエンドが融合したアーキテクチャの複雑さをReact本体のみでカバーすることはできないからです。
また、Webページを作るには、デザインを考えることも欠かせません。デザインのためにはデザイン用のライブラリも必要になりますね。
こうして書くと絶望的な気分になるかもしれませんが、視点を変えてみるとその絶望感も薄れるかもしれません。
それは、「ライブラリはあったら便利だから導入されている」という点です。
あなたがもし現場でwebページの開発を担当することになり、幸運にも先輩がいるのなら、「なんでこのライブラリって使ってるんですか?」って聞いてみるのも手かもしれません。
もしあなたが一人ぼっちで戦う孤独な開発者なのであれば、qiitaの質問コーナーを利用したり、chatGPTに聞いてみるのもいいかもしれません。ユースケースを例示してもらって、公式リファレンスと見比べながら、そのライブラリの素敵な部分を見出してみることをおすすめします。
javascriptに負けない
ReactはJavascript用のライブラリであるため、javascriptを読んだり書いたりしないと当然扱うことが出来ません
初見では読みづらい短縮表現があるので、読みづらかったものを一覧形式で軽く紹介します。
構文 | 名前 | 解説 |
---|---|---|
object?.property | オプショナルチェイニング | object が null / undefined のときは undefined を返し、それ以外のときは property を取得する |
const 変数名 = (引数) => { 処理...} | アロー関数 | 変数に関数を代入する 引数は()の中で指定する つまり、(引数)で処理を実行する、という意味 ()=>{処理}なら引数なし |
配列.map(任意の変数名=> 処理) | map関数 | 配列の要素を取り出して、一つずつ処理を行う。 処理が終わると新しい配列を返す。 よくあるitem => item.idみたいなのは、配列の各要素に勝手にitemという名前を付けているだけ 2 |
配列.forEach(任意の変数名=> 処理) | forEach関数 | 配列の要素を取り出して、一つずつ処理を行う。 処理が終わるとundefinedを返す。 よくあるitem => item.idみたいなのは、配列の各要素に勝手にitemという名前を付けているだけ 2 |
変数名 ?? デフォルト値 | null合体演算子 | 変数がundefinedまたはnullの場合のデフォルト値を設定する。三項演算子みたいでわかりづらい |
判定 ? 値1 : 値2 | 三項演算子 | 判定がtrueなら値1、falseなら値2を返す。ちなみに判定の方法がヤバい3 |
[...]or{...オブジェクト名}or{...オブジェクト名,プロパティ名:値} | スプレッド構文 | 超便利、利用方法が多岐にわたる。詳しくは「スプレッド構文」でググってください(これだけで記事一本書けます) |
さいごに
ここまで書いたように、Reactは非常に独特な技術ライフサイクルを形成しています。ただ、使いこなすことによって、洗練されたアニメーション、複雑な処理、ユーザーのアクションに素早く反応する"Reaction"の良いwebページを書くことができます。
また、UIはシステムを構築する中で多くの場合で関わってくる分野であるため、非常に需要の高い分野でもあります。そのため、人手不足に陥りやすい分野でもあるのです。
あなたがフロントエンドを学ぶことによって、世界中のユーザーや、FEエンジニア不足に喘ぐ企業を救うことが出来る……かもしれません。
そんなヒーローの誕生に、この記事が一役買っていたのなら幸いです。
React、サイコー!
-
ちなみに、Reactの公式リファレンスにはそのものずばりの「Reactの流儀」というページがありますが、経験者向けの難しい話が書いてあるので、初学者の状態で読むのはお勧めしません。頭がパンクします。ただ、いいことは書いてあるので、経験値が増えたら読んでみてくださいね。 ↩
-
ちなみに、予約語として
index
array
が用意されており、mapの第2引数、第3引数として利用できるため、変数名には使えないから気を付けてください。indexは配列の添え字(0から始まるやつ)で、arrayは配列自身を指します。 ↩ ↩2 -
javascriptにおけるtrueやfalseは"trueなもの(truthy)"と"falseなもの(falsy)"という概念が存在し、それぞれtruthyなのが「空文字以外の文字列」「0以外の数字」「オブジェクト」「true」「配列(空配列含む)」などです。逆にfalsyな値は「null」「undefined」「0」「false」などです ↩