Reactパッケージ@JavaScript¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. Reactパッケージとは¶
フロントエンドのパッケージ群である。
以下のパッケージを組み合わせて、最低限アプリケーションを作成できる。
- react
- react-dom
- react-scripts (webpack、babelからなる)
02. セットアップ¶
UIレンダリングパターン¶
▼ CSRモード¶
エントリーポイント (main ファイル) でDOMツリーのルートによる render 関数の実行が必要である。
import {StrictMode} from "react";
import {createRoot} from "react-dom/client";
import {App} from "./App.tsx";
const rootElement = document.getElementById("root");
if (!rootElement) {
throw new Error("Failed to find the root element");
}
const root = createRoot(rootElement);
root.render(
<StrictMode>
<App />
</StrictMode>,
);
ワンラインで実装する場合、以下となる。
import {StrictMode} from 'react'
import {createRoot} from 'react-dom/client'
import {App} from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App/>
</StrictMode>,
)
▼ SSRモード¶
記入中...
▼ SSGモード¶
記入中...
03. エクスポート¶
デフォルトエクスポート¶
記入中...
名前付きエクスポート¶
名前付きエクスポートの場合、インポート側は定義した名前以外でインポートできない。
// App.tsxファイル
const Hello = () => {
return (
<p>
Hello, <b>React!</b>
</p>
);
};
// 名前付きエクスポート
export const App = () => {
return (
<div className="App">
<Hello />
</div>
);
};
import {StrictMode} from "react";
import {createRoot} from "react-dom/client";
import "./index.css";
// App.tsxファイルから名前付きエクポート (App) をインポートする
import {App} from "./App.tsx";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>,
);
04. Reactによる独自コンポーネント¶
Reactによる独自コンポーネントとは¶
Reactは汎用的なUIレンダリングロジックと状態管理ロジックを提供する。
これ使用して、汎用的なUIレンダリングロジックと状態管理ロジックのクラスまたは関数を定義できる。
import React from "react";
React.Component(クラスコンポーネント)¶
▼ クラスコンポーネントとは¶
他ファイルで使用できる汎用的なクラスを定義する。
クラスコンポーネントより関数コンポーネントがより推奨である。
import React, {Component} from "react";
export class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {count: 0};
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
</div>
);
}
}
関数コンポーネント¶
▼ 関数コンポーネントとは¶
他ファイルで使用できる汎用的な関数を定義する。
クラスコンポーネントより関数コンポーネントがより推奨である。
import React from "react";
export const MyComponent = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
</div>
);
};
▼ async 宣言不可¶
Reactでは、関数コンポーネントで async 宣言は使用できない仕様になっている。
非同期関数を useEffect 関数に渡したうえで、これをreactコンポーネントにする必要がある。
▼ 引数がある場合はProps型を定義する¶
関数コンポーネントに引数がある場合、引数の型としてProps型を定義するとよい。
import React from "react";
type MyComponentProps = {
initialCount?: number;
label: string;
};
export const MyComponent = ({ initialCount = 0, label }: MyComponentProps) => {
const [count, setCount] = React.useState(initialCount);
return (
<div>
<p>
{label}: {count}
</p>
<button onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
};
// 呼び出し先
<MyComponent label="Count" initialCount={5} />
クラスまたは関数コンポーネントで使用できる関数¶
▼ React.memo¶
コンポーネントをキャッシュする。
useMemo のコンポーネント版である。
import React from "react";
type Props = { value: number };
const Counter = React.memo(function Counter({ value }: Props) {
return <div>{value}</div>;
});
05. フック¶
useEffect¶
▼ useEffectとは¶
reactコンポーネント内で、状態の変化に応じて非同期処理を使用できるようにする。
フロントエンドの文脈では、レンダリング後のデータ変更処理を非同期処理とするとよく、レンダリング後にこの処理を useEffect 関数で実行する。
// useEffect関数内でsetFooState関数を実行し、state変数を動的に変更する
const [fooState setFooState] = useState("<初期値>");
useEffect(
// 実行したい無名な非同期関数
() => {
// state変数に値を設定する
setFooState(response.data);
return () => {
// 事後処理
};
},
// useEffectを再度実行したい場合に、[state]を設定する
// 省略すると、1回だけ実行する
[state],
);
return のみを使用すると、useEffect で早期リターンも実装できる。
const [fooState setFooState] = useState("<初期値>");
useEffect(
() => {
const data = response.data
if(data){
// state変数に値を設定する
setFooState(response.data);
return;
}
// state変数に値を設定する
setFooState(null);
},
[state],
);
▼ 第一引数¶
*実装例*
import {useEffect, useState} from "react";
export const MyComponent = () => {
// useEffect関数内でsetFooState関数を実行し、state変数を動的に変更する
const [fooState setFooState] = useState("");
useEffect(
// 実行したい無名な非同期関数
() => {
const fetchData = async () => {
const response = await axios.get("https://example.com");
// state変数に値を設定する
setFooState(response.data);
};
// 非同期処理を実行する
fetchData();
},
[],
);
// stateを出力する
// state変数はJS型オブジェクトであり、ドットでアクセスできる
return <pre>{state.fooKey}</pre>;
};
▼ 第二引数¶
*実装例*
import React, {useState, useEffect} from "react";
import "./App.css";
export const App = () => {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);
useEffect(
() => {
console.log("useEffectが実行されました");
},
// Stateのcount変数の値が変わるたびに、useEffectが実行される。
[count],
);
return (
<div className="App">
<h1>Learn useEffect</h1>
<h2>Count: {count}</h2>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>+</button>
<h2>Count2: {count2}</h2>
<button onClick={() => setCount2((prevCount) => prevCount + 1)}>+</button>
</div>
);
};
▼ 実行の順番¶
useEffect 関数はレンダリング後に実行される。
そのため、useEffect 関数の後の関数が useEffect 関数よりも先に実行される。
import React, { useState, useEffect } from 'react';
import './App.css';
export App = () => {
const [count, setCount] = useState(0);
// 実行 (1)
console.log('useEffect実行前です');
useEffect(
// 実行したい無名な非同期関数
() => {
// 実行 (3)
console.log('useEffectが実行されました');
});
// 実行 (2)
console.log('useEffect実行後です');
return (
<div className='App'>
<h1>サンプル</h1>
<h2>countの値: {count}</h2>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>+</button>
</div>
);
}
useMemo¶
処理負荷を軽減するため、該当のstate変数の状態が変わらない限り処理結果を再利用する。
useEffect で複数のstate変数の状態を管理している場合に、一方の変数の状態だけを再利用できる。
import {useState, useMemo} from "react";
export default function App() {
// state変数
const [count, setCount] = useState(0);
const [text, setText] = useState("");
const caluculatedValue = useMemo(() => {
// ここで配列を操作するなどの負荷の高い処理を実行する
return count * 2;
// count変数の状態が変わらない限り再計算されず、前回の結果を再利用する
}, [count]);
// 画面上の操作によってtextとcountが変わることがあり、textだけの変更ではcountを再利用する
return (
<div>
<h1>サンプル</h1>
<p>countの値: {count}</p>
<p>caluculatedValueの値: {caluculatedValue}</p>
<button onClick={() => setCount((c) => c + 1)}>increment</button>
<br />
<br />
<input
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="テキストの値"
/>
</div>
);
}
useState¶
reactコンポーネント内で状態を管理できるようにする。
state 変数と setState 関数を返却するため、これを任意の名前の変数に格納する。
import {useEffect, useState} from "react";
// state変数をfooState変数とし、setState関数をsetFooState変数とする
const [fooState setFooState] = useState("<初期値>");
// state変数はJS型オブジェクトであり、ドットでアクセスできる
console.log(state.fooKey);
// state変数はJS型オブジェクトであり、JSONを確認したい場合はJSON.stringify関数で変換する
console.log(JSON.stringify(state));
06 イベント¶
SyntheticEventを拡張したChangeEvent¶
import React from "react";
export const DateTimePicker = () => {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
// input属性で表示される画面で選択した値がevent変数に入る
console.log("event:", event);
console.log("event.target:", event.target);
console.log("event.target.value:", event.target.value);
};
return (
// クリックすると、handleChangeが発火する
<input
type="datetime-local"
onChange={handleChange}
/>
);
};