Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版
2023/0522
じゃけぇ
目次
セクション1:はじめに
セクション2:CodeSandboxについて
セクション3:再レンダリングの仕組みを知りレンダリングを最適化する
セクション4:様々なCSSのあてかたに触れる
セクション5:ルーティングの基礎(ReactRouter)
セクション6:コンポーネントの分割方法(Atomic Design)
セクション7:グローバルなstate管理を知る
セクション8:JsonPlaceholderでのデータ取得解説
セクション9:React×TypeScript(基礎編)
セクション10:React×TypeScript(実践編)
セクション11:カスタムフック
セクション12:実践アプリ作成(ChakraUI)
セクション13:さいごにとこれから
雑学
2022年3月にReact18がリリースされた
ライブラリによっては、最初に以下のコメントを書く必要がある、とのこと。
/** @jsxRuntime classic */
/** @jsx jsx */
StrictMode
セクション1:はじめに
セクション2:CodeSandboxについて
セクション3:再レンダリングの仕組みを知りレンダリングを最適化する
コンポーネントの「再レンダリング」が発生する3条件
1:stateが更新された
2:propsが更新された
3:親コンポーネントが更新された
propsが、参照渡しのセンスで、渡した後にpropsが更新されたら子コンポーネントも更新される、らしい?
いや、そういう意味では無いと思う。「propsは渡された以降は、更新を参照されない」はず。
memo
コンポーネントを memo で囲うことで「親の再レンダリングに伴う自身の再レンダリング」の際「propsが前回と同じなら、再レンダリングを省略する」動きに出来る。
? memoなしでも最初から「無駄な再レンダリング」起きなかったよ。
v18では memoつき がデフォルトの挙動になっている、ということでは。
useCallback
memo の コールバック関数版。
コールバック関数の「参照されるたびに再生成判定」される問題を防ぐ。
これも、v18ではデフォルトで対応済み?そもそもの「無駄な再レンダリング」が発生しなかった。
まぁ「知っておく」のは大事なこと。
useMemo
memo の変数版。
学び:
「無駄な子コンポーネントの再レンダリング」が気になったら、memo, useCallback の適用を確認する!
セクション4:様々なCSSのあてかたに触れる
WebSandbox でも、sassは使える!
Dependencies : node-sass を検索してクリックすることで、package.json にsassが追加される。
scssを記述するファイルの名称は ".*¥.module¥.scss"。
scssファイルをインポートする際は import classes from "./Hoge.module.scss"。
クラスhogeをJSX上で適用する場合は <div className="classes.hoge"/>
styled-jsx
styled-jsx ライブラリをインポートすると使える。
JSXの中で直接CSSを記述するスタイル。
使わない。使わせない。
<style jsx="true"> </style>
中にはCSSをベタ書きできる。
疑似要素は使えない。
使わない。
Next.js に標準で入っている。
styled-components
const StyledDiv = styled.divbackground: pink; の形で「スタイルが当たったコンポーネント」を書ける。
sass書式での記載が可能。疑似要素も使える。
やめよう、こういうの!
css は 専門ファイルに分けろ!
emotion
@emotion/react
@emotion/styled
「Emotionは色々な記法に対応している」やめろーー!!
セクション5:ルーティングの基礎(ReactRouter)
Reactでの画面遷移の方法はいくつかある
最もメジャーなのはReactRouter
大前提として、React=SPA。
ReactRouter(v6)×React(v18)のサンプル
code:js
// 必要なインポート
import { BrowserRouter, Link, Routes, Route } from "react-router-dom";
import "./styles.css";
import { Home } from "./home";
import { Page1 } from "./page1";
import { Page2 } from "./page2";
export default function App() {
return (
// Routes は、BrowserRouter内で使用する。
// また、BrowserRouterは、Reactプロジェクト内で1度しか使えない。
<BrowserRouter>
<div className="App">
// 内部リンクを貼る
<Link to="/">Home</Link>
<br />
<Link to="/page1">Page1</Link>
<br />
<Link to="/page2">Page2</Link>
<br />
<Home />
<Page1 />
<Page2 />
</div>
// URLによる出し分け部分
<Routes>
// exact をつける=完全一致した場合。つけない=(上から順に)正規表現で一致したらそこが処理される。
// ReactRouter v6 からは exact 不要?
<Route exact path="/" element={<Home />} />
<Route exact path="/page1" element={<Page1 />} />
<Route exact path="/page2" element={<Page2 />} />
</Routes>
</BrowserRouter>
);
}
Route の定義は上記のようにベタにやってもいいし、配列に突っ込んでまとめて出力しても良い。
import {useParams} from "react-router-dom" で、URLパラメータを取得できる。
import {useLocation} from "react-router-dom"で、クエリパラメータを取得できる。
URLSearchParam
ES6標準。URLクエリー文字列の操作をサポート。
Link のパラメータで state を指定することで、遷移先コンポーネントに state を引き渡すことが出来る。
import {useHistory} from "react-router-dom" で、JS起点の画面遷移を実現できる。
セクション6:コンポーネントの分割方法(Atomic Design)
AtomicDesign
デザインシステム
画面を5段階に分割する
ATOMS:原子。ボタン、テキストボックス、アイコン。
MOLECULES:分子。アイコン+メニュー名、プロフィール画像+テキストボックス、アイコンセット。
ORGANISMS:有機体。ツイート入力エリア、サイドメニュー、1つのツイートエリア。
TEMPLATES:ひな形、レイアウト。サイドメニュー、ツイートエリア、コンテンツ。
PAGES:ページ。最終的に表示される一画面(=具体的なデータが入ったテンプレート)。
活かし方:
ソースコード上に、各段階のフォルダを作り「その層はそのフォルダで」集めて作っていく。
でもさ、一回ぐちゃっと作ってみないと「正しい各層」って見えてこないもんだよね。
<dl><dt><dd> いままで知らなかった!
<li>の派生、見たいなHTMLタグ。
Atomic Design は「基本的な考え方」。真に受けすぎない、必勝法ではない。
セクション7:グローバルなstate管理を知る
グローバルなstate管理
どうもよくわからない。
「データ主導でReactコンポーネントの更新をかける」という発想、らしい。
それって「すげぇ良いソリューション」を自前で開拓しちゃってるんですけど。。
Context
import {createContext} from "react"
Provider
「その種類のデータを提供するもの」。具体的には、Contextを返す。
Provider & Context の例:
code:js
import {createContext} from 'react'
export const UserContext = createConst({});
export const UserProvider = (props) => {
const {children} = props;
return (
<UserContext.Provider>
{children}
</UserContext.Provider>
)
};
整理
コンポーネントで「stateとしてContextを直接参照」することにより、データ主導でのコンポーネント更新(再描画)が可能になる。
知識として、 Context, Provider は知っておく。
自分では使わない。「データはグローバルデータで一元化、ReactコンポーネントはHTML出力装置」という理解のため。
Recoil
Context, Provider の次世代ソリューション。
atom という単位でグローバルステートを定義する。
useContext
recoil
セクション8:JsonPlaceholderでのデータ取得解説
jsonPlaceholder:サービス名、サイト名。テスト補助サービス。
RESTAPIを登録するとURLが発行され、それをコールするとJSONが返って来る。
lowDB
簡易なJS上のDB。
結論:
簡易スタブとしてとても良い。
共有できる点がGood。
ただ、セキュリティの観点から「こんな感じのをローカル環境で用意しておこう」になると思う。
セクション9:React×TypeScript(基礎編)
TypeScript
MicroSoftが開発したオープンソース。
JS + 型。
TypeScript の 型
code:ts
let bool: boolean = true;
let num: number = 1;
let str: string = "A";
let ary2: number[] = 0,1,2; let any1: any = 0;
const func = (): void => {
return;
}
let null1: null;
let undefined1: undefined;
let object1: object = {};
let object2: {id: number, name: string} = {id: 1, name: "name"};
tsconfig.json でTypeScript挙動の調整が可能。
セクション10:React×TypeScript(実践編)
typescriptプロジェクトの立ち上げ方法
npx create-react-app my-app --template typescript
型の定義
code:ts
type TodoType = {
userId: number;
name?: string: // nameは必須ではない
}
// コンポーネントのpropsに型を指定することで、型チェックが可能になる
export const NewComponent = (props: TodoType) => {
}
// 指定タイプから、一部のプロパティだけを抜き出して参照することも可能
export const NewComponent = (props: Pick<TodoType, "userId" | "name">) => {
}
// オミット指定も可能
export const NewComponent = (props: Ommit<TodoType, "userId" | "name">) => {
}
// 同じことをFC型指定でも書ける(これならクラスコンポーネントでいいじゃん)
export const NewComponent: FC<TodoType> = (props) => {
}
オプショナルチェイニング
Ruby でいう &.
TypeScript では ?. で書ける
ライブラリが「独自の型定義」を公開している場合もある
react-router-dom の場合は @types/react-router-dom
この辺りはライブラリごとに異なる。マニュアルを見ること。
当然、type の定義があれば開発時有利になる。
セクション11:カスタムフック
要は、共通関数化。イディオム的なテクニック。
特定の共通処理を個別のクラス/関数に切り出し、外部から呼び出し/戻り値の取得をしよう、という話。
共通関数の「状態」も返そう、というのが新鮮。
文法的にも、特別なことはない。
「外部のクラスのメンバをコール」と、した場合、クラスのコールの方が素直で直感的、かなぁ。
カスタムフックでも良いっちゃ良いが。
「カスタムフックの呼び出しで返される値群の説明」が必要になる分、面倒。
セクション12:実践アプリ作成(ChakraUI)
CSSフレームワーク
Reactにフォーカスしている
類似:
MATERIAL-UI
TailwindCSS
Semantic UI React
Ant Design
WebSandbox + CSS でその場でデザインしていくのは、芸として楽しそう。
HTML navタグ
Drawer
スライドで表示されるタイプのデザイン
ChakraUIの見学
うーん……
出来合いのCSSパーツは、たしかに便利そうだ
ただ、それらもひっくるめて「最終的にSCSSでベタ書きしたい」かなぁ
セクション13:さいごにとこれから
受講してみて
これで、Reactの中級までは「知ってます!」言えるようになった!
おまけで、TypeScriptの入門もできた。
type、Pick、Ommit、コンフィグファイル、オプショナルチェイニング、ライブラリごとのts
SPAでもURLは使う、らしい。
MPAとは違い(react-router-domを使った場合)ブラウザのURLは更新されるが、サーバへのアクセスは発生しない
目的は以下の2点
リソースの一意指定
URL:必ずあるもの、Params:任意のもの
名前空間の提供
React 17 と 18 でいろいろちがう、かも知れない。
コンポーネントの memo の要不要など。
カスタムフック、それ、普通にクラスでやっていけばいいだけでは?