こんにちはSAです。今回Reactの学習をしました。
その際、React入門後のステップアップとして、Udemyの「Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版」を受講した。
Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版
ただ、講義で扱われていたReactのバージョンは17であり、現在主流のReact 19とは差があったため、この機会に「React 17から19で何が変わったのか」を確認してみた。
- レンダリングとメモ化
- cssの当て方
- ReactRouterも大きく変化
- コンポーネントの分割
- グローバルなstateの管理
- まとめ
・レンダリングとメモ化
講義ではコンポーネントのmemo化(React.memo)を推奨していた。
Reactでは親コンポーネントが再レンダリングされたら自動的に子コンポーネントも再レンダリングされる。
そのため子コンポーネントでレンダリングに重い処理を使用していたら親コンポーネントの変更で子コンポーネントが親コンポーネントの変更のたびに無駄にレンダリングし直しになり、速度が遅くなる原因になりうる場合があった。
それを防止するために子コンポーネントをmemo化すると親コンポーネントが描画しなおしても子コンポーネントが再レンダリングしないようにできる。
|
1 2 3 4 5 |
const Greeting = memo(function Greeting({ name }) { return <h1>Hello, {name}!</h1>; }); export default Greeting; |
しかし、現在はReact Compilerの登場により、多くの場合で手動のmemo化が不要になっている。
React Compilerが自動的に最適化を行うため、以前ほど「とりあえずmemo化する」という必要性は薄くなっているようだ。
・CSSの当て方
講義では様々なCSSの当て方を学習した。これについては、プロジェクトの実装方針に従い使い分けていくことになりそう。
inline Styles
|
1 2 3 4 5 6 7 8 9 10 11 12 |
export const InlineStyle = () => { const containerStyle = { border: "solid 2px" }; const titleStyle = {}; const buttonStyle = {}; return ( <div style={containerStyle}> <p style={titleStyle}>- Inline Styles -< /p> <button style={buttonStyle}>FIGHT !!< /button> </div> }; |
CSS Modules
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
.container { border: solid 2px #392eff; border-radius: 20px; padding: 8px; margin: 8px; display: flex; justify-content: space-around; align-items: center; } .title { margin: 0; color:#3d84a8; } .button { background-color: border: none; padding: 8px; border-radius: 8px; color:#abedd8; } |
|
1 2 3 4 5 6 7 8 9 10 |
import classes from "./CssModules.module.scss"; export const CssModules = () => { return ( <div className={classes.container}> <p className={classes.title}>- CSS Modules -< /p> <button className={classes. button}>FIGHT! !< /button> </div> ) }; |
Styled jsx (react 標準ではない)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
export const StyledJsx = () => { return ( <> <div> <p>- Styled JSX -< /p> <button>FIGHT! !< /button> </div> <style jsx="true">{` .container { border: Tolid 2px #392eff; border-radius: 20px; padding: 8px; margin: 8px; display: flex; justify-content: space-around; align-items: center; `}</style> </> ); }; |
Styled components(React 標準ではない)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import styled from "styled-components"; export const StyledComponents = () => { return ( <SContainer> <STitle>- styled components -< /STitle> <SButton>FIGHT !!< /SButton> </SContainer> ); }; const SContainer = styled.div` border: solid 2px #392eff; border-radius: 20px; padding: 8px; margin: 8px; display: flex; justify-content: space-around; align-items: center; const STitle = styled.p` margin: 0; color: #3d84a8`; const SButton = styled.button` background-color: #abedd8; border: none; `; I |
・React Routerも大きく変化
講義ではReact Router v5が使われていたが、現在はv7となっており、記法が大きく変わっている。
v5
|
1 2 3 |
<Switch> <Route path="/users/:id" component={User} /> </Switch> |
v6以降
|
1 2 3 |
<Routes> <Route path="/users/:id" element={<User />} /> </Routes> |
component 属性ではなく、element にJSXを渡す形式になった。
また、ネストルートの書き方もシンプルになっている。
v5
|
1 2 3 |
<Route path="/users"> <UsersLayout /> </Route> |
v6以降
|
1 2 3 |
<Route path="/users" element={<Layout />}> <Route path=":id" element={<User />} /> </Route> |
v7ではRemixとの統合も進んでいる
さらに調べてみると、React Router v7では Remix との統合が進み、ルーティング時にデータ取得を行ってから画面表示する仕組みが強化されているようだ。
この辺りはまだ理解が追いついていないため、以下の記事を参考にした。
コンポーネントの分割
Atomic Designとは、UIコンポーネントを粒度ごとに分類して設計する考え方である。
以下の5段階に分けて構成される。
ATOMS → MOLECULES → ORGANISMS → TEMPLATES → PAGES
ATOMS (細胞)
ボタン、テキスト、アイコンのみなど一つの部品
MOLECULES (分子)
検索フォーム、ラベル付き入力欄などATOMSを組み合わせた部品
ORGANISMS (有機体)
ユーザーカード、コメント欄などある程度独立した機能を持つコンポーネント。
TEMPLATES (テンプレート)
ヘッダーメインフッターなど複数の有機体。
PAGES(ページ)
完成した1ページ。
Templatesに実際のデータを流し込み、ユーザーが閲覧するページとして成立したものを指す。
グローバルなstateの管理
Reactでは、デフォルト機能であるContext APIを使用してグローバルなStateを管理できる。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import React, { createContext, useState } from "react"; export const UserContext = createContext({}); export const UserProvider = (props) => { const { children } = props; const [userInfo, setUserInfo] = useState(null); return ( <UserContext.Provider value={{ userInfo, setUserInfo }}> {children} </UserContext.Provider> ); } |
使用側では useContext を使って値を取得・更新する。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
const history = useHistory(); const { setUserInfo } = useContext(UserContext) ; const onClickAdmin =() => { setUserInfo({ isAdmin: true }); history.push("/users"); } const onClickGeneral = () => { setUserInfo({ isAdmin: false }); history.push("/users"); } |
講義では状態管理ライブラリとしてRecoilを使用していたが、現在は以前ほど勢いがないようだ。
最近ではZustandなどの軽量なライブラリの人気が高まっているらしく、プロジェクトの規模や要件に応じて選定するのがよさそうだ。
まとめ
短期間でも、React周辺の記法や開発の常識は大きく変化していると感じた。
特に、以前は手動で行うのが一般的だった memo による最適化が、現在ではReact Compilerによって自動化されつつあり、React全体として開発をよりシンプルにしようとしている流れを感じた。
また、講義で使用されていたライブラリの勢力図も変化しており、以前主流だったものが現在では別の選択肢に置き換わりつつあることから、ライブラリ選定を定期的に見直す重要性も実感した。
以前は当たり前だった実装方法が、現在では不要になっていたり、より簡潔な形へ変化していたりするため、継続的に情報をアップデートしていく必要があると感じた。
