Reactメモ
useState(stateフック)
構文
function ImageGallery() {
const [index, setIndex] = useState(0);
// ...
-
sethoge
で「変数の値の更新」と「表示の更新」が可能 -
const
宣言が一般的(setを通さない直接代入を防ぐため?) -
useState()
に引数を渡すのは初期値を設定する時だけ?
props
親から子へ受け渡すもの
useContext
を使用すると孫以上でも直接の受け渡しが可能
useRef(refフック)
構文
function Form() {
const inputRef = useRef(null);
// ...
- stateと違い、refの値を更新してもコンポーネントの再レンダは起こらない
- Reactパラダイムからの「避難ハッチ」として、React外のシステムを扱う時に役立つ
- 具体的には、DOMノードなどを格納する
参考文献
Reactにおける「コンポーネント」とは
React アプリはコンポーネントで構成されています。コンポーネントとは、独自のロジックと外見を持つ UI(ユーザインターフェース)の部品のことです。
React におけるコンポーネントとは、マークアップを返す JavaScript 関数です。
React のコンポーネント名は常に大文字で始める必要があり、HTML タグは小文字でなければなりません。
function MyButton() {
return (
<button>I'm a button</button>
);
}
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
<MyButton /> が大文字で始まっていることに注意してください。
まとめ:コンポーネント = マークアップを返すJS関数
- コンポーネントは大文字
- HTMLタグは小文字
- コンポーネントは、別のコンポーネントにネストできる
JSX
- タグは閉じる必要がある(例:
<br />
) -
return
できるのは単一のタグ(よって、<>...</>
で囲んだりする)
function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}
- classは
class
属性ではなくclassName
属性(例:<img className="avatar" />
) -
{}
を使うことで、JSとリンクできる。
return (
<h1>
{user.name}
</h1>
);
// {"hoge" + "fuga"} などの演算も可能
- 条件分岐の特別な構文
&&
<div>
{isLoggedIn && <AdminPanel />}
</div>
// 以下と(ほぼ)同一
let content;
if (isLoggedIn) {
content = <AdminPanel />;
}
return (
<div>
{content}
</div>
);
-
useState
を使用するにはimport
が必要(import { useState } from 'react';
)-
useState
はインスタンス的で、それぞれが異なる状態を保持する(例:ボタンのクリック回数)
-
Hook
use で始まる関数は、フック (Hook) と呼ばれます。
フックには通常の関数より多くの制限があります。フックはコンポーネントのトップレベル(または他のフック内)でのみ呼び出すことができます。条件分岐やループの中で useState を使いたい場合は、新しいコンポーネントを抽出してそこに配置します。
useState テクニック
「別のボタンでも同じ状態を保持したい」場合
「ボタンごとに状態を持つ」のではなく。
🙅♂️ | 🙆♂️ |
---|---|
まず、MyButton から MyApp に、state の移動を行います。
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
// ... we're moving code from here ...
}
次に、MyApp から各 MyButton に state を渡し、共有のクリックハンドラも一緒に渡します。以前に <img> のような組み込みタグで行ったときと同様、JSX の波括弧を使うことで MyButton に情報を渡すことができます。
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
このように渡される情報は props と呼ばれます。MyApp コンポーネントは count 状態と handleClick イベントハンドラを保持しており、それらをどちらも props として各ボタンに渡します。
最後に、MyButton を変更して、親コンポーネントから渡された props を読み込むようにします。
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
Reactの流儀📝
◆ 実装の順番
1. コンポーネントに分解
まず最初に行うのは、モックアップのすべてのコンポーネントとサブコンポーネントを四角で囲んで、それぞれに名前を付けていくことです。
2. 静的なバージョンを作成
引用とテクニック
アプリの実装に取り掛かりましょう。最も分かりやすいアプローチは、インタラクティブな要素はまだ加えず、単にデータモデルから UI をレンダーするバージョンを作成することです。
通常、単純な例ではトップダウンで作業する方が簡単であり、大規模なプロジェクトではボトムアップで進める方が簡単です。
3. 最小限のUI設計
state
/ props
/ そこから計算されるもの に分割する。何をstate
とするかは後述。
state
を保持するコンポーネントを特定
4. 特定方法の例
- その
state
に基づいたレンダーを行う「すべてのコンポーネント」を特定する - それらの最上位コンポーネントを見つける
- そのコンポーネント / より親のコンポーネント / 新規コンポーネント を適切に選択し
state
を保持させる
5. 子→親のデータフローを追加する
state
であれば、setState
関数を渡すこと
例
function FilterableProductTable({ products }) {
const [filterText, setFilterText] = useState('');
// ~~~
return (
<div>
<SearchBar
filterText={filterText}
onFilterTextChange={setFilterText} />
function SearchBar({...}) {
return {
<input
type="text"
value={filterText}
placeholder="Search..."
onChange={(e) => onFilterTextChange(e.target.value)}
/>
}
}
state
を使用する判断基準
◇
- 時間が経っても変わらないものですか? そうであれば、state ではありません。
- 親から props 経由で渡されるものですか? そうであれば、state ではありません。
- コンポーネント内にある既存の state や props に基づいて計算可能なデータですか? そうであれば、それは絶対に state ではありません!
-> 「変化する」「渡されない」「計算不可能な」データにstateを使う
命名規則等
React
◆ Rule
- ひとつのファイルにひとつのコンポーネント
- 複数のステートレス・単純なコンポーネントはまとめることを許容する
- デフォルトエクスポートでもコンポーネントに名前をつける
◇ 命名規則
- Reactコンポーネント:アッパーキャメル
- インスタンス:ローワーキャメル?
インスタンスとは?(推測)
import React from 'react';
// パスカル記法: コンポーネントの定義
const MyComponent = ({ name }) => {
return <div>Hello, {name}!</div>;
};
// キャメル記法: インスタンス化して使用
const myComponentInstance = <MyComponent name="Jane" />;
export default function App() {
return (
<div>
{myComponentInstance}
</div>
);
}
- ファイル名 = コンポーネント名
- 短く・直感的で・説明的(S-I-D)
- 単語の短縮は避ける
- Prefix? / Action / High Context / Low Context パターン(A/HC/LC Pattern)
◆ A/HC/LC Pattern
例:get
/ User
/ Messages
Prefix?
主に変数の意味を強化する。
- is
bool
- has
bool
- should
bool
:条件分岐の判定条件として使う
function shouldUpdateUrl(url, expectedUrl) {
return url !== expectedUrl
}
if(shouldUpdateUrl(a, b)) {
// update url
}
- min / max
num
:制限・境界を明示 - prev / next:前後関係を明示。状態遷移の文脈
- 単数 / 複数
Action
- get
- set
- reset
- remove / add
- delete / create
- compose:既存のデータから新しいデータを作成
function composePageUrl(pageName, pageId) {
return pageName.toLowerCase() + '-' + pageId
}
- handle:callback
そもそもReactについて
開発元:Meta
2011年 Facebook内部で利用開始
2013年 OSSとして公開
Reactの特徴
- viewに特化→「ライブラリ」と自称
- コンポーネント指向
→ Model / Controller は不要 → サーバーを通さず、フロントで終始できる。 - JSX(必須ではない)→当時は不評だった。HTML/CSS/JSを分けるほうが良いとされるため
- 宣言的UI(what)(対義語:命令的(how))
- 仮想DOM→現実のDOMは遅いことが多い
ただし、最適化方法の一つであり、これを使うことで遅くなることもある。
また、現在のreactは仮想DOMとは呼ばない。react nativeなど仮想domを使わない環境もあるため。
ドキュメント上は「reactツリー」と呼ばれている
なお、差分検出機能は「reconciliation」と呼ばれている - Learn Once, Write Anywhere(ネイティブアプリでも、的な意味?)
間違ったベストプラクティスを押し付けない→フォルダ構成など
デメリット
View以外をどうするかはアプリ開発側で考える必要がある
(ユーザー権限などを、reduxなどのサードパーティに頼らないといけない)
Children プロパティ
便利そう。ただし・・・
詳細は理解できなかった