React Fundamentals
Components
function Hello() {
return <h1>Hello from a component!</h1>;
}
export default Helloコンポーネントの使用 :
import Hello from "./components/Hello";
function App() {
return (
<>
<Hello />
</>
)
}React.memo
- 用途 : 関数 コンポーネントをラップして、props が変更 されていない場合 に不要 な再 レンダリングを防止 。
const MyComponent = React.memo((props) => {
return <div>{props.value}</div>;
});Use Case: 関数 コンポーネントがあり、特定 の状況 で props が変更 されないことが確実 な場合 、レンダリングパフォーマンスを最適化 するために使用 。
Props
コンポーネント間
で共有
される読
み取
り専用
のプロパティ。
親 コンポーネントから子 コンポーネントにデータを渡 すことができる。
親 コンポーネントから子 コンポーネントにデータを渡 すことができる。
<Component key=value />// App.jsx
function App() {
return (
<>
<Hello name="ABC" msg="Here" emoji="💥" />
<Hello name="XYZ" msg="Nothing" emoji="🎇" />
</>
);
}
// Hello.jsx
function Hello({ name, msg, emoji }) {
return (
<div>
<h1>
Hello {name}, {msg} {emoji}
</h1>
</div>
);
}Immutability
不変性
function Hello(props) {
// props.name = "Replace"; // Error: Uncaught TypeError: "name" is read-only
return (
<div>
<h1>
Hello {props.name}, {props.msg} {props.emoji}!
</h1>
</div>
);
}PropTypes
渡
される値
が正
しいデータ型
を持
つことを保証
するメカニズム。
age: PropTypes.number
Lists & Keys
export default function Fruits() {
const fruits = ["Apple", "Mango", "Orange", "Banana", "Pineapple"];
return (
<div>
<ul>
{fruits.map((fruit) => (
<li key={fruit}>{fruit}</li> // 正確: ユニークな key を追加
))}
</ul>
</div>
);
}Portal
Modal/Dialog (ダイアログ)
- 確認 ダイアログ
- メッセージ通知
- フォーム入力
フローティング要素
- Tooltip (ツールチップ)
- Dropdown Menu (ドロップダウンメニュー)
- Select ドロップダウン
- DatePicker (日付 選択 )
グローバル通知
- Toast 通知
- エラーメッセージ
- Loading 状態
特殊 UI
- 右 クリックメニュー (Context Menu)
- 仮想 キーボード
- 画像 プレビュー
- 動画 プレーヤー
- ドラッグメニュー
特殊 シナリオ
- iframe 内 の要素
- Shadow DOM 外 の要素
- サードパーティパッケージの統合
使用 タイミング:
- 現在 の DOM 階層 制限 から抜 け出 す必要 がある場合
z-index/overflow問題 を回避 する場合- グローバル UI コンポーネントを共有 する必要 がある場合
- 異 なるフレームワークのコンポーネントを統合 する必要 がある場合
Hooks
useState
状態
変数
と setter 関数
を作成
し、仮想
DOM 内
で値
を更新
するために使用
。
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}- Native (素 の JS との比較 )
<p id="count">Count: 0</p>
<button id="increment">Increment</button>
<script>
let count = 0;
document.getElementById('increment').addEventListener('click', function() {
count++;
document.getElementById('count').textContent = 'Count: ' + count;
});
</script>useEffect
用途
- イベントリスナー (Event Listeners)
- DOM 操作
- サブスクリプション (Subscriptions、リアルタイム更新 など)
- API からデータを取得
- コンポーネントのアンマウント時 のクリーンアップ作業
React にいつコードを実行 するかを指示
- コンポーネントが再 レンダリングされた時
- コンポーネントがマウントされた時
- 特定 の値 の状態 が変更 された時
useEffect(() => {}) // 毎回レンダリング後に実行
useEffect(() => {}, []) // マウント時に一度だけ実行
useEffect(() => {}, [value]) // マウント時 + value が変更された時に実行function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []); // 空配列はコンポーネントのマウント時に一度だけ実行を意味
return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>;
}useRef
値
が変更
されても再
レンダリングを引
き起
こさない。
コンポーネントに情報 を記憶 させたいが、その情報 が新 しいレンダリングをトリガーしないようにしたい場合 に使用 。
コンポーネントに情報 を記憶 させたいが、その情報 が新 しいレンダリングをトリガーしないようにしたい場合 に使用 。
- Use Cases
- DOM 要素 へのアクセス / 操作
- フォーカス (Focus)、アニメーション、トランジションの処理
- タイマー (Timers) とインターバル (Intervals) の管理
function FocusInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}useContext
複数
のコンポーネント階層
間
で値
を共有
でき、各
階層
で手動
で props を渡
す必要
がない。
- 使用
シナリオ
- グローバル状態 (テーマ、言語 切替 など)
- 異 なる階層 のコンポーネント間 のデータ伝達
Provider
// Context を作成し値を提供Consumer
// Context 内の値を使用useMemo
- 用途
:
- パフォーマンス最適化 、不要 な重複 計算 を回避
- **「計算 結果 」**をキャッシュ
- 使用
シナリオ:
- 再 レンダリング中 に高負荷 な計算 の実行 を回避
- 大規模 データリストのレンダリングを最適化
const memoizedValue = useMemo(() => {
return complexCalculation(a, b); // 計算結果をキャッシュ
}, [a, b]);useCallback
- 用途
:
- パフォーマンス最適化 、不要 な関数 の再 作成 を回避
- **「関数 自体 」**をキャッシュ
- 使用
シナリオ:
- 関数
を
propsとして子 コンポーネントに渡 す必要 がある場合 (React.memo と併用 ) - 関数 参照 を安定 させ、子 コンポーネントの不要 な再 レンダリングを防止
- 関数
を
const memoizedCallback = useCallback(() => {
doSomething(a, b); // 関数参照をキャッシュ
}, [a, b]);useReducer
- 用途 : 複雑 な状態 ロジックを管理 。
- 使用
シナリオ:
- マルチステップフォーム
- 画像 ドラッグ機能
- 複雑 な状態 切替 ロジック (Redux に類似 )
useImperativeHandle
- 用途 : 親 コンポーネントがアクセスできる子 コンポーネントのインスタンス値 をカスタマイズ。
- 使用
シナリオ:
- 子 コンポーネントの内部 実装 を隠 し、特定 のメソッドのみを公開 (手動 で子 コンポーネントのアニメーションをトリガーするなど)
- 複雑 な操作 可能 なコンポーネント (カスタムポップアップ操作 など)
useLayoutEffect
- 用途 : DOM 更新後 、ブラウザが描画 する前 に同期的 に実行 。
- 使用
シナリオ:
- DOM レンダリング後 に即座 に測定 または修正 を行 う必要 がある場合
- 複雑 な同期 アニメーションやレイアウトロジックの実装
useId
- 用途 : ユニークで安定 した ID を生成 。
- 使用
シナリオ:
- 複数 要素 のユニークな Key 値 を生成
- フォームラベルと入力 フィールドのアクセシビリティを関連 付 け
useTransition
- 用途 : ノンブロッキングの過渡的 な UI 更新 を管理 。
- 使用
シナリオ:
- ページ切替時 に過渡 状態 を表示
- 高頻度 計算 結果 の遅延 レンダリングを最適化
useDeferredValue
- 用途 : 値 の更新 を遅延 させ、パフォーマンスを向上 。
- 使用
シナリオ:
- 高速 入力時 の UI のカクつきを回避
- 高 パフォーマンスな検索 入力 ボックス
useSyncExternalStore
- 用途 : 外部 データソースをサブスクライブし、データの同期 を維持 。
- 使用
シナリオ:
- カスタムグローバル状態 管理 ツール
- サードパーティデータベースへの接続 (Redux など)
useInsertionEffect
- 用途 : DOM 変更前 に CSS スタイルを注入 。
- 使用
シナリオ:
- 動的 なスタイル挿入 (Emotion や styled-components など)
学習 順序 (Orders)
初心者 : 最 も使用 される Hooks を習得
useStateuseEffectuseContext
中級 : パフォーマンス最適化 関連 の Hooks を学習
useMemouseCallbackuseRef
上級 : 複雑 な状態 とロジックを処理 する Hooks
useReduceruseImperativeHandle
特定 用途 : 特殊 なシナリオに対応 する Hooks を学習
useLayoutEffectuseTransitionuseDeferredValueuseSyncExternalStoreuseInsertionEffectuseId
useStateとuseReducerはコンポーネント内部 の状態 管理 に使用 。useEffect,useLayoutEffect,useInsertionEffectはすべて副作用 処理 に使用 され、違 いは実行 タイミング。useContextはコンポーネント間 でデータを共有 するために使用 。useRefとuseIdは参照 とユニーク ID の管理 に使用 。useTransitionとuseDeferredValueはパフォーマンス最適化 に使用 され、不要 な UI ブロッキングを軽減 。useSyncExternalStoreは外部 (非 React) の状態 をサブスクライブするために使用 。
Purity
React コンポーネントは純粋 関数 であるべき:
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}- Native (素 の JS との比較 )
<h1 id="greeting"></h1>
<script>
let name = 'Alice';
document.getElementById('greeting').textContent = 'Hello, ' + name + '!';
</script>Strict Mode
import React from 'react';
function MyApp() {
return (
<React.StrictMode>
<App />
</React.StrictMode>
);
}特性 説明
- 開発 モードでは、特定 のライフサイクルが2回 実行 される
- 副作用 が純粋 かどうかを確認 するのに役立 つ
- 非推奨 の API 使用 と安全 でないライフサイクルを識別
Fragments
function List() {
return (
<>
<li>Item 1</li>
<li>Item 2</li>
</>
);
}Context API
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
function ThemedComponent() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<div>
<p>Current Theme: {theme}</p>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
</div>
);
}Portals
function Modal() {
return ReactDOM.createPortal(
<div className="modal">This is a modal</div>,
document.getElementById('modal-root')
);
}Error Boundaries
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error(error, info);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}Suspense
import { Suspense, lazy } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}Event Handlers
主
に
入力値 が変更 されるたびに関数 をトリガー
input, textarea, select, radio などのフォーム要素
で使用入力値 が変更 されるたびに関数 をトリガー
Mouse Events
- onClick
- onDoubleClick
- onMouseDown
- onMouseUp
- onMouseMove
- onMouseEnter
- onMouseLeave
- onMouseOver
- onMouseOut
- onContextMenu
Form Events
- onChange
- onSubmit
- onReset
- onInvalid
- onSelect
Focus Events
- onFocus
- onBlur
Keyboard Events
- onKeyDown
- onKeyUp
- onKeyPress
Clipboard Events
- onCopy
- onCut
- onPaste
Touch Events
- onTouchStart
- onTouchMove
- onTouchEnd
- onTouchCancel
Drag & Drop Events
- onDrag
- onDragStart
- onDragEnd
- onDragEnter
- onDragLeave
- onDragOver
- onDrop
Media Events
- onPlay
- onPause
- onPlaying
- onEnded
- onLoadStart
- onLoadedData
- onLoadedMetadata
- onError
- onVolumeChange
- onTimeUpdate
- onSeeking
- onSeeked
Animation Events
- onAnimationStart
- onAnimationEnd
- onAnimationIteration
Transition Events
- onTransitionEnd
- onTransitionStart
Scroll Events
- onScroll
- onWheel
Window Events
- onResize
- onError
- onLoad
- onUnload
- onBeforeUnload
Visibility Events
- onVisibilityChange
Image Events
- onLoad
- onError
OnChange
function TextInput() {
const [value, setValue] = useState('');
function handleChange(e) {
setValue(e.target.value);
}
return <input value={value} onChange={handleChange} />;
}React Query
Server Sideデータ処理 に特化- API リクエスト
- データキャッシュ
- データ同期
- エラーリトライ
- 状態 更新
Tanstack Router
zustand
useShallow- サブスクライブされた state を浅 く比較 し、不要 な再 レンダリングを削減
- オブジェクトや配列 型 の state に特 に有効
- React.memo の比較 ロジックに類似
Middleware
immer
- 可変 な方法 で不変 な更新 を書 くことを許可
- 複雑 な状態 の更新 ロジックを簡素化
- 不変性 (Immutability) を自動 処理
subscribeWithSelector
- 特定
の
state変更 を監視 指定 / 特定 条件 でサブスクリプションをトリガー可能
devtools
- Redux DevTools との統合
- タイムトラベルデバッグをサポート
- 状態 変更 の履歴 を確認 可能
persist
- 状態 の永続化 機能 を提供
- ストレージエンジンをカスタマイズ可能
- 暗号化 と圧縮 をサポート
App.jsx
test.jsx