将来を見据えたウェブ・アプリケーションの構築:The Codestのエキスパート・チームによる洞察
The Codestが、最先端技術を駆使してスケーラブルでインタラクティブなウェブアプリケーションを作成し、あらゆるプラットフォームでシームレスなユーザー体験を提供することにどのように秀でているかをご覧ください。The Codestの専門知識がどのようにデジタルトランスフォーメーションとビジネス...
多くのインタビューをする中で、経験豊富なプログラマーでさえ、Hooksの見分け方に問題を抱えていることに気づいた。そこで、この記事ではフックの使い方を説明しようと思う。
フックについて覚えておくべき最も重要なこと:
使用
;インポート { useState,useEffect } from "react";
エクスポートデフォルト function FunctionComponent() {
const [value, setValue] = useState(1);
const [doubleValue, setDoubleValue] = useState(1);
if (value > 3) { doubleValue, setDoubleValue
useEffect(() => setDoubleValue(value * 2),[value]);
}
return (
<>
<p>{シングル${値}}。ダブル ${doubleValue}`}。</p>
<button onclick="{()" > setValue(値+1)}>チェック</button>
</>
);
}
```
最初はeslintから警告が出ます:
<code>srcFunctionComponent.js
Line 11:5: React フック "useEffect "は条件付きで呼び出されます。 <strong>Reactフック</strong> はどのコンポーネントでも全く同じ順序で呼び出されなければならない .eslintreact-hooks/rules-of-hooks をレンダリングする
見ての通り、これはeslintの警告に過ぎない。 関数コンポーネント
/* eslint-disable react-hooks/rules-of-hooks */
しかし、それはフックを実行する条件を満たすまでしか機能しない。次に見るのはこのエラーだ。
捕捉されないエラー:前回のレンダリング時よりも多くのフックをレンダリングしました。
React 5
関数コンポーネント FunctionComponent.js:11
React 12
unstable_runWithPriorityスケジューラ.development.js:468
React 17
js index.js:7
js main.chunk.js:905
Webpack 7
react-dom.development.js:15162
なぜこのようなことが起こるのか?ReactはHookが呼び出される順番に依存している。ReactはuseEffectのために何を返すべきかわからないからだ。
eslintは強力なツールであり、多くの潜在的なバグやエラーを発見してくれます。eslintの警告を無効にするのは危険なことです。警告を無視することでアプリがクラッシュするかどうか、常にチェックしてください。
どう見えるかは、おそらくご存知でしょう😉。
const [value, setValue] = useState(0);
つまり、ステート(反応値)、アップデート・ファンクション(セッター)、実際のフック(ファンクション)、オプションの初期値の4つの要素がある。なぜ配列を返すのか?好きなように再構築できるからだ。
さて、最後の要素である初期値に注目したい。初期状態を渡すには2つの方法がある:
const [value, setValue] = useState(0);
const [value, setValue] = useState(() => { [value, setValue] = useState(() => { [value, setValue] = useState(() => {
console.log("INIT");
return 0;
});
各レンダーで最初の方法が本当に呼び出されることを確認するには?関数を作成し、それを初期状態として渡します:
const checkInit = () => { {チェックインします。
console.log("INIT");
return 0;
};
const [value, setValue] = useState(checkInit());
```
そして今度は2つ目の方法でパスを出す:
const checkInit = () => { {チェックインします。
console.log("INIT");
return 0;
};
const [value, setValue] = useState(() => checkInit());
```
クールだろ?
もうひとつ、アプリのフローにバグを生じさせる可能性があることがある。
setValue(1);
そうだね......でも、もし以前の状態に基づいて状態を更新したい場合はどうすればいいんだろう?
setValue(value + 1);
でも、セッター関数を2回呼び出そうとしたら?前の状態に基づいて状態を更新する推奨される方法は、関数を使用することです。前の状態を参照していることが保証されます。
setValue((prevState) => prevState + 1);
// オブジェクトを使用します:
setUser((prevState) => ({ ...prevState, lastName: "Brzeczyszczykiewicz" }));
このHookは2つの引数を取り(2つ目の引数はオプション)、副作用を処理するために使用します。そして、2番目の引数として何を渡すかによって、Hookは違った形で呼び出されます:
useEffect(()=>{を使用します。
doSomething();
});
useEffect(() => {)
doSomething();
}, []);
useEffect(()=>{を使用します。
doSomething(value);
}, [値]);
useEffectを使えば、クリーンアップと呼ばれるものを使うことができる。何のために使うのか?とても便利なのだが、イベント・リスナーのクリーニングに最適だと思う。例えば、ある状態に依存するイベントリスナーを作りたいとします。ステートが変わるたびに新しいイベントリスナーを追加するのは避けたい。このようなことを避けるには、クリーンアップ機能を使うのがよい。どうすればいいのか?useEffectに戻り関数を追加するだけです。
useEffect(() => {」とする。
console.log("side effect 1", count);
リターン() => {
console.log("DESTROYED 1");
};
});
useEffect(())=>の{。
console.log("side effect 2", count);
戻り値() => {
console.log("DESTROYED 2");
};
}, []);
useEffect(())=>の{。
console.log("side effect 3", count);
戻り値() => {
console.log("DESTROYED 3");
};
}, [count]);
```
useEffect Hookの中なので、returnは依存配列に応じて呼び出されます。各レンダリング時、最初のレンダリング時のみ、依存配列の値が変更された時などです。しかし、コンポーネントがアンマウントされると、cleaningは第2引数に関係なく呼び出されます。リターン コード はフックからの実際のコードの前に呼び出される。それはとても論理的なことで、まず古いものをきれいにして、それから新しいものを作る。そうだろ?
useEffect(() => {
// addEventListener
console.log("追加");
return () => { // remove Event Listener
// removeEventListener
console.log("Remove");
};
}, [値]);
そこで、まず 取り除く
メッセージ 追加
.
useEffectとその中の非同期コードを使うときに気をつけなければならないことがある。以下のコードを見てほしい:
useEffect(() => {」を使用します。
fetch("https://picsum.photos/5000/5000").then(() => {)
setValue((prevState) => prevState + 1);
});
}, []);
最初は大丈夫そうに見える。データを取得し、データが来たら状態を更新する。そして、ここに罠がある:
そのような警告を受けることもある:マウントされていないコンポーネントで React の状態更新を実行できません。これはエラーではありませんが、アプリケーションでメモリ・リークが発生していることを示しています。修正するには、useEffect クリーンアップ関数ですべてのサブスクリプションと非同期タスクをキャンセルします。
コンポーネントはその間にアンマウントできるが、アプリは約束が果たされた後もそのコンポーネントの状態を更新しようとするからだ。どのように対処すればよいのだろうか?コンポーネントが存在するかどうかをチェックする必要がある。
useEffect(() => {)
let mounted = true;
fetch("https://picsum.photos/5000/5000").then(() => {)
if (mounted) {
setValue((prevState) => prevState + 1);
}
});
return () => { {マウントされた
mounted = false;
};
}, []);
```
注意:非常によく似たHook => useLayoutEffect()があります - このコールバックはコンポーネントをレンダリングした後に実行されますが、Domが視覚的に更新される前に実行されます。getBoundingClientRect()を使用するときに便利ですが、デフォルトではuseEffectを使用する必要があります。なぜか?エフェクトフックの中に複雑なコードがある場合、視覚的な更新をブロックしてしまう可能性があるからです。
何のため?小道具を渡すことなくデータを共有する。以下の要素で構成される:
const user = {
name: "Adam"、
lastName:"Kowalski"、
};
export const UserContext = createContext(user);
;
```
子プロセスでは、コンテキストをインポートしてuseContext Hookを呼び出し、そのコンテキストを引数として渡す必要がある。
import { UserContext } from "./App";
const { name }.= useContext(UserContext);
戻り値 <h1>名前}さん、こんにちは。<>
```
ほら。見た目はクールだ。主にテーマなどのグローバルデータを渡すのに使う。非常に動的な変更を伴うタスクでの使用はお勧めしません。
もちろん、カスタムコンテキスト・プロバイダーとカスタムHookを作れば、ボイラープレートを減らすことができる。
useStateのように、ステートを管理し、ステートが変更されたときに再レンダリングすることができます。reduxのreducerに似ている。ステートのロジックが複雑な場合は、useStateよりもこちらの方がよいでしょう。
const [state, dispatch] = useReducer(reducer, initialArg);
また、useReducerに渡すことができる3つ目の引数、init関数もある。
const [state, dispatch] = useReducer(reducer, initialArg, init);
何のために使うのか?状態を初期値に戻したいときに使う。以下に例を示します:
// 親
// 子
関数 init(initialNumber) {
return { number: initialNumber };
}
関数reducer(state, action) {
switch (action.type) {
case "change":
return { number:Math.random() };
case "reset":
return init(action.payload);
デフォルトでは
throw new Error();
}
}
エクスポートデフォルト関数 ChildComponent({ getFactorial }) {
const [state, dispatch] = useReducer(reducer, initialNumber, init);
return (
<>
<h2>番号:{state.number}。</h2>
<button
onclick="{()" > dispatch({ type: "reset", payload: initialNumber })})。
>
リセット
</button>
<button onclick="{()" > ディスパッチ({ type: "change" })}>ドロー</button>
</>
);
}
どんなときに使うのか?参照対等を実現したいとき(それによって作成される関数の数を減らしたいとき)。このフックは、値を返すuseMemoとは異なり、関数を返します。
例親コンポーネントに関数を作成し、それをpropsで渡す。
// 親
const getSquaredValue = () => count * count;
...
return (
を返します。
)
そして、その関数を依存配列に追加した後、エフェクト・フックが何回呼び出されるかを、子コンポーネントでチェックする:
// 子
useEffect(() => {)
console.log("getSquaredValue", getSquaredValue());
}, [getSquaredValue]);
レンダリングするたびにコンソールにログが記録される!たとえ 二乗値()
関数は変更されなかった。しかし、この関数をuseCallbackでラップすることで、これを避けることができる。
const getSquaredValue = useCallback(() => count * count, [count])
また、この関数にいくつかのパラメータを渡すこともできる:
const getSquaredValue = useCallback(
(乗数) => count * count * 乗数、
[カウント]
);
const memoizedValue = useMemo(() => { {メモを使用します。
return doSomething(value);
}, [値]);
2つのシナリオに限って使うべきだ:
つ目のケースをもう少し詳しく見てみよう。オブジェクトを依存関係としてuseEffectを使いたい。オブジェクトは参照によって比較されるため、useEffectはレンダリングのたびに呼び出されることになる。このようなことを避けるために、useEffectをuseMemoと組み合わせて、そのようなオブジェクトをメモし、そのメモしたオブジェクトを依存配列に渡すことができます。簡単な例:
まず、useMemoなしでやってみる:
const hobbit = { name: "Bilbo" };
useEffect(() => {)
console.log("Hello ", hobbit.name);
}, [hobbit]);
```
また、警告も受ける:
hobbit'オブジェクトは、useEffectフック(49行目)の依存関係をレンダリングごとに変更させます。これをuseEffectコールバック内に移動します。あるいは、'hobbit' の初期化を独自の useMemo () Hook でラップします。
次にuseMemoを使ってみよう:
const hobbit = useMemo(() => { {{名前 "ビルボ"}}を返す。
return { name: "Bilbo" };
}, []);
console.log("Hello ", hobbit.name);
}, [hobbit]);
```
最も重要なことは、useRefはレンダリングサイクルに関連していないため、(useStateのように)再レンダリングをトリガーしないことです。
const ref = useRef(0);
保存された値を呼び出すには、カレント・プロパティ(refはオブジェクト)を使用する必要があります。 ref.カレント
Hookが使える2つ目のケースは、HTML内部の要素を参照することだ。各要素はref属性を持っている。そのため、フォーカスやイベントなどを扱うことができる。
3つ目のケースは、制御不能なコンポーネントを扱うためにrefを使用することである。詳しくは 反応ドキュメント,
が、要するにこんな感じだ:
エクスポート デフォルト関数 UncontrolledForm() {
const input = useRef();
const handleSubmit = (e) => { {.
e.preventDefault();
console.log(input.current.value);
};
return (
に次のように入力します。
</form
</form
);
}
見ての通り、イベント・ハンドラはなく、入力された値を記憶しているだけだ。基本的なフォームを扱うときに、保存した値を必要なとき(送信するときなど)に読みたいときに最適です。
おまけ:以前のステート値を覚えておく必要があるときに便利。useEffectフックを使えば、ref.に状態を渡すだけでよい。
const [value, setValue] = useState("");
let prevValue = useRef("");
useEffect(() => {)
prevValue.current = value;
}, [値]);
setValue(e.target.value)}>;
おわかりのように、フックはそれほど目立つものではない。それらを組み合わせることで、多くの問題を解決することができる。このトピックを勉強することで、きっと大きな利益を得られるだろう。
そして、カスタムフックもある...。
結論として Reactフック はその方法に革命をもたらした。 React開発者 アプローチビル ウェブアプリケーション .機能コンポーネントの状態とライフサイクルを管理する、より直感的で効率的な方法を提供することで、フックは、次のような機能コンポーネントの不可欠な一部となっています。 React開発 .
あなたが経験豊富な開発者であれ、Reactを使い始めたばかりであれ、最も人気のあるフックとその使用例を理解することは非常に重要です。useState、useEffect、useContextなどのフックがあります、 Reactコンポーネント は、よりクリーンで再利用可能なコードで構築できる。さらに カスタムフック により、開発者は複数のコンポーネント間でロジックをカプセル化して共有することができ、コードの再利用性とモジュール性を促進することができます。Reactが進化を続け、新機能を導入していく中で、フックがフレームワークの可能性を最大限に活用する上で中心的な役割を果たすことは間違いない。
だから、小さな機能アプリであれ、大規模なウェブ・アプリケーションであれ、次のようなものを採用することだ。 Reactフック は、あなたの開発ワークフローを強化し、堅牢で機能性に富んだ Reactアプリケーション .
第1部終了
続きを読む