【React】FormのTextareaをコンポーネント化する方法を解説

JavaScript

こんにちは、かつコーチです。

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では制御されたコンポーネントを使用するのがベストプラクティスとされています。

これにより、入力内容を状態として管理しやすくなり、複雑なフォームの処理が簡単になります。

しかし、特定のシンプルなケースでは、アンコントロールされたコンポーネントの方が適している場合もあります。

用途に応じて、どちらのアプローチが適しているかを判断してください。

タイトルとURLをコピーしました