【React.js】useTransitionとuseIdの使い方をご紹介(React hooksを学ぶ)
目次
今回は、React hooksのuseTransitionとuseIdの二つのフックを紹介します。
useTransitionは次の画面を裏側でレンダリングさせ特定の値の更新を遅延させるフックであり、useIdはクライアント側とサーバー側で安定した一意のIDを作成するフックです。
今回でReact hooksの記事は最後になります。
ここまでのReact hooksの記事は以下になります。
【React.js】useStateとuseEffectの使い方をご紹介(React hooksを学ぶ)
https://www.dailyupblog.com/web_development/1888/
【React.js】useContextとuseReducerの使い方をご紹介(React hooksを学ぶ)
https://www.dailyupblog.com/web_development/1926/
【React.js】useCallbackとuseMemoの使い方をご紹介(React hooksを学ぶ)https://www.dailyupblog.com/web_development/1956/
【React.js】useRefとuseImperativeHandleの使い方をご紹介(React hooksを学ぶ)
https://www.dailyupblog.com/web_development/1978/
【React.js】useLayoutEffectとuseDeferredValueの使い方をご紹介(React hooksを学ぶ)https://www.dailyupblog.com/web_development/2005/
useTransitionについて
useTransitionは前回のuseDeferredValueと同様に、React18から追加された比較的新しいフックです。
こちらも同じように、指定した値の更新を遅延させるフックになりますが、useDeferredValueとは処理が異なり、useTransitionは、現在の画面表示は変わらず、裏側でレンダリングを行うため、ユーザーはレンダリング中も画面操作が可能となります。
つまりノンブロッキングの状態になるわけです。
ノンブロッキングとは、何か重たい処理などをしている間に他の実行可能な処理は進めて、実行中の重たい処理が完了しないと次の処理に移行できないものに関しては、処理を一旦ストップするといった挙動になります。
例えば下記の場合のように3つの処理があったとします。
処理A・処理B・処理C
処理Aと処理Bは同時実行可能
処理Cは処理Aが完了しないと実行できない。
上記の簡単な例だと、処理Cを実行するには、処理Aが完了しないと実行できないため、処理をブロック状態にしますが、処理Bに関しては、実行可能なため、処理Aと同時進行で実行します。
これがノンブロッキングであり、ユーザー操作のパフォーマンスを向上させます。
useTransitionでは、このノンブロッキング処理が可能になります。
現在の画面を保持したまま(レンダリングさせない)、裏側でレンダリングを実行するため、ノンブロッキングな処理といえます。
実際の例を見てみましょう。
「components」フォルダ内にUseTransition.tsxファイルを作成してください。
その中に下記のように記述してください。
import React, { useState, useTransition } from "react";
import styled from "styled-components";
const UseTransition = () => {
const keywords = [
"りんご",
"みかん",
"ぶどう",
"もも",
"なし",
"すいか",
"さくらんぼ",
"いちご",
"ばなな",
"かき",
];
const Div = styled.div`
margin-top: 10px;
`;
const Span = styled.span`
display: inline-block;
margin-right: 10px;
background: #e0ffff;
border: 1px solid #1e90ff;
padding: 0 0.4em;
border-radius: 3px;
`;
const items = keywords.map((val) => `${val}`);
const [isPending, startTransiton] = useTransition();
const [updateValue, setUpdateValue] = useState("");
const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
startTransiton(() => {
setUpdateValue(e.target.value);
});
};
return (
<>
<input type="text" onChange={onChangeHandler} />
{isPending && <p>Pending...</p>}
<Div>
{items
.filter((it) => {
return it.includes(updateValue);
})
.map((it, i) => (
<Span key={i}>{it}</Span>
))}
</Div>
</>
);
};
export default UseTransition;
※少し、styled componentsを使ってスタイルをつけていますが、不要であればそこは省いても結構です
上記の例は、キーワードを含めた配列を用意し、フォームに入力した文字列とこの配列の値を比較して、一致したもののみを表示する、キーワードの絞り込み検索の例になります。
この挙動の中で、useTranstionを使用しています。
今回は、くだものの名前のキーワード配列を用意しました。
上記例のようにまず下記のように、useTransitionでisPendingとstartTransitonを用意しておきます。
const [isPending, startTransiton] = useTransition();
そして、イベントハンドラで、「startTransiton」で、遅延させたい処理を指定します。
今回は、「setUpdateValue」を指定して、「updateValue」が入力された値に更新される処理を遅延対象とします。
このイベントハンドラをinputのonChange属性に指定することで、inputに入力されるたびにstartTransitonの遅延処理が走るようにしました。
下記の記述ですが、
{isPending && <p>Pending...</p>}
これは、useTransitionで遅延処理させている間に、表示させるDOMを指定しています。
今回の例であれば、処理は軽いため遅延処理といってもすぐ実行されますが、処理が重い時の場合は、上記の「Pending…」の文言が表示されます。
そして、filterとmapを使って、くだもの配列の中から、入力された値と一致するものを表示させます。
実際の挙動を確認してみましょう。
まず、下記のように、くだもの配列の値が全て表示されていればOKです。
そして、フォームに「い」というひらがなを入力してみてください。
下記のように、「い」が含まれる「すいか」と「いちご」のみ絞り込み表示されればOKです。
今回の例をまとめると、フォームに入力し、入力した値とくだもの配列内の値を比較する「updateValue」を更新する処理をuseTransitionの遅延対象としています。
そのため、更新から配列内の全ての値を比較して画面に表示するまでの処理に時間がかかる場合(比較する配列の値が膨大な場合など)でも、画面はそのままの状態をキープして裏側で処理からレンダリングまでを行ってくれるので、かなりパフォーマンスが向上されるといえるでしょう。
useIdについて
useIdも、React18から追加された新しいフックで、クライアント側とサーバー側で安定した一意のIDを作成するフックです。
IDはランダムに生成されるため、アプリケーション内のコンポーネントで重複しない異なるIDになることが保証されています。
例えばinputにつけるidなどは、今までは手動で設定する必要がありました。
手動でつけるため、他コンポーネント内のIDと重複する可能性があり、それはエラーの原因となります。
useIdは、絶対に重複しないようにランダムにIDを生成してくれるため、idを手動で付けるというプロセスを簡素化することができます。
使い方はとてもシンプルです。
実際の使用例を見てみましょう。
「components」フォルダ内にUseId.tsxファイルを作成して、下記のように記述してください。
import { ChangeEvent, FormEvent, useId, useState } from "react";
const UseId = () => {
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const id = useId();
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
alert(`名前:${name}\n年齢:${age}歳\nID:${id}`);
};
const handleAgeChange = (event: ChangeEvent<HTMLInputElement>) => {
const newAge = parseInt(event.target.value);
setAge(newAge);
};
return (
<>
<form onSubmit={handleSubmit} action="" method="post">
<label htmlFor={`${id}-name`}>
名前:
<input
id={`${id}-name`}
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
<br />
<label htmlFor={`${id}-age`}>
年齢:
<input
id={`${id}-age`}
type="number"
value={age}
onChange={handleAgeChange}
/>
歳
</label>
<br />
<input type="submit" />
</form>
</>
);
};
export default UseId;
上記の例は、フォームに名前と年齢を入力して、submitボタンを押すと、アラートで入力内容が表示される簡単な例になります。
labelのhtmlForと、inputのidは、同じ値を入れる必要があり、そうすることでテキストが入力に関連づけられます。
ここのidにuseIdを使用しています。
useIdは下記のように使用します。
const id = useId();
ここでは特に引数は取りません。
これで簡単に一意のidを生成することができました。
あとは、このidを設定するだけです。
今回は、名前と年齢で異なるidを設定するために、「${id}-name」と「${id}-age」のようにしました。
また、アラートで入力内容を出すときに、一緒に生成したidも表示するようにしました。
実際に挙動を確認してみましょう。
下記のように入力した内容が表示されれば、OKです。
表示されたIDを確認すると、「:r0:」のようにコロン付きでidが生成されているのがわかります。
このuseIdで生成されるidですが、下記の点に注意して使用してください。
- CSSセレクタではサポートされていないので、使用しない
- リスト内のアイテムのキー生成には使用しない
この2つの場合では使用できないので、お気をつけください。
最後に
今回は、useTransitionとuseIdについて紹介しました。
今回で、全6回にわたるreact hooksの記事は終わりです。
様々なreact hooksを今まで学んできました。
これらを開発の場でうまく使いこなし、アプリケーション開発に役立てることができれば良いです。
これらのreact hooksをうまく使い分けることで、よりパフォーマンスの良い優れたアプリケーションが開発できれば幸いです。
前回:【React.js】useLayoutEffectとuseDeferredValueの使い方をご紹介(React hooksを学ぶ)
https://www.dailyupblog.com/web_development/2005/