こんにちは、かつコーチです。
Reactを扱っているとコンポーネントにすることがあると思います。
今回はFormでよく扱われるTextareaについてコンポーネントにする方法を解説します。
完成コード
使い分けが必要かと思いますが、2種類作成しました。
作成例1:
import { forwardRef, useEffect, useRef } from 'react';
const Textarea = forwardRef(({ className = '', isFocused = false, ...props }, ref) => {
const textareaRef = useRef(null);
useEffect(() => {
if (isFocused && textareaRef.current) {
textareaRef.current.focus();
}
}, [isFocused]);
return (
<textarea
{...props}
className={`flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-600 focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 resize-none ${className}`}
ref={ref ? ref : textareaRef}
/>
);
});
export default Textarea;
作成例2
import { forwardRef, useEffect, useRef } from 'react';
const Textarea = forwardRef(({ className = '', isFocused = false, ...props }, ref) => {
const textareaRef = useRef(null);
useEffect(() => {
if (isFocused && textareaRef.current) {
textareaRef.current.focus();
}
}, [isFocused]);
return (
<textarea
{...props}
className={`flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-600 focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 resize-none ${className}`}
ref={ref ? ref : textareaRef}
>
{props.value ?? ''}
</textarea>
);
});
export default Textarea;
違いと使い分け
作成例1(value属性使用)
- Reactの制御されたコンポーネント:
value
属性を使うと、textarea
の内容が完全にReactの状態管理下に置かれます。入力内容が変わるたびに、onChange
イベントで状態を更新する必要があります。これにより、内容を完全に制御できる利点があります。 - フォームの管理が簡単: フォーム全体のデータを一元管理しやすくなります。特に、フォーム送信時に簡単にデータを取得できるため、複雑なフォームの場合は非常に便利です。
作成例2(childrenとしてvalueを設定)
- アンコントロールされたコンポーネント: この方法では、
textarea
の初期値を設定しますが、その後の入力内容はReactの状態管理から外れます。入力内容の変更を追跡したり、動的に内容を更新する必要がない場合に適しています。 - 単純なケース: 簡単なフォームや、入力内容が頻繁に変更されない場合には、このアプローチが簡潔です。
value
属性の変更に対するオーバーヘッドがなく、パフォーマンス面で若干の利点があります。
推奨される使い分け
- 制御されたコンポーネントを使用する場合(推奨):
- フォームデータを一元管理し、状態を正確に追跡する必要がある場合。
- 入力内容をリアルタイムでバリデーションする場合。
- 入力内容に基づいて他の部分を動的に更新する必要がある場合。
- アンコントロールされたコンポーネントを使用する場合:
- 初期値を設定するだけで、その後の入力内容を追跡する必要がない場合。
- 入力内容の更新が少なく、単純なフォームの場合。
結論
ほとんどの場合、Reactでは制御されたコンポーネントを使用するのがベストプラクティスとされています。
これにより、入力内容を状態として管理しやすくなり、複雑なフォームの処理が簡単になります。
しかし、特定のシンプルなケースでは、アンコントロールされたコンポーネントの方が適している場合もあります。
用途に応じて、どちらのアプローチが適しているかを判断してください。