React コンポーネント開発:制御コンポーネントと非制御コンポーネントを使い分ける

2024-04-02

React 制御コンポーネントと非制御コンポーネント

制御コンポーネント

制御コンポーネント は、コンポーネント自身の状態 (this.state) で入力値を管理します。親コンポーネントから props を介して値を受け取り、その値を更新することで、子コンポーネントのレンダリングを制御します。

特徴

  • 状態を this.state で管理
  • 親コンポーネントから props で値を受け取る
  • 親コンポーネントから props を介して値を更新することでレンダリングを制御
  • フォーム要素など、動的な入力値を扱うコンポーネントに適している

class ControlledInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.initialValue,
    };
  }

  handleChange = (event) => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <input
        type="text"
        value={this.state.value}
        onChange={this.handleChange}
      />
    );
  }
}

この例では、ControlledInput コンポーネントは initialValue という props を受け取り、その値を this.state.value に格納します。ユーザーが入力値を変更すると、handleChange 関数が呼び出され、this.state.value が更新されます。そして、value プロパティが更新されることで、コンポーネントが再レンダリングされます。

非制御コンポーネント

非制御コンポーネント は、DOM 自身で入力値を管理します。コンポーネントは props を介して初期値を設定できますが、その後は DOM の値を参照することで入力値を取得します。

  • 状態を DOM 自身で管理
  • DOM の値を参照することで入力値を取得
  • シンプルなコンポーネントに適している
const UncontrolledInput = ({ initialValue }) => {
  const [value, setValue] = React.useState(initialValue);

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return (
    <input
      type="text"
      defaultValue={initialValue}
      onChange={handleChange}
    />
  );
};

この例では、UncontrolledInput コンポーネントは initialValue という props を受け取り、その値を defaultValue プロパティとして設定します。ユーザーが入力値を変更すると、handleChange 関数が呼び出され、value 変数が更新されます。

使い分け

制御コンポーネントと非制御コンポーネントは、それぞれ異なる状況で使い分けられます。

制御コンポーネント は、以下の状況で適しています。

  • 入力値の検証やバリデーションを行うコンポーネント
  • 親コンポーネントから子コンポーネントへの値の受け渡しが必要なコンポーネント

React コンポーネントには、状態の管理方法によって 制御コンポーネント非制御コンポーネント の 2 種類があります。それぞれの特徴と使い分けを理解することで、状況に応じて適切なコンポーネントを選択することができます。




制御コンポーネント

class ControlledInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.initialValue,
    };
  }

  handleChange = (event) => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <input
        type="text"
        value={this.state.value}
        onChange={this.handleChange}
      />
    );
  }
}

const App = () => {
  const [count, setCount] = React.useState(0);

  const handleCountChange = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <ControlledInput initialValue={count} />
      <button onClick={handleCountChange}>Count Up</button>
    </div>
  );
};

App コンポーネントでは、ControlledInput コンポーネントを count という変数の値でレンダリングしています。count 変数が更新されると、ControlledInput コンポーネントが再レンダリングされ、新しい値が表示されます。

非制御コンポーネント

const UncontrolledInput = ({ initialValue }) => {
  const [value, setValue] = React.useState(initialValue);

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return (
    <input
      type="text"
      defaultValue={initialValue}
      onChange={handleChange}
    />
  );
};

const App = () => {
  const [count, setCount] = React.useState(0);

  const handleCountChange = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <UncontrolledInput initialValue={count} />
      <button onClick={handleCountChange}>Count Up</button>
    </div>
  );
};

上記のコード例は、制御コンポーネントと非制御コンポーネントの基本的な動作を示しています。それぞれのコンポーネントの特徴と使い分けを理解することで、状況に応じて適切なコンポーネントを選択することができます。




制御コンポーネントと非制御コンポーネントのその他の方法

制御コンポーネント

  • React.createRef を使用して、DOM 要素への参照を取得し、その参照を使用して値を更新することができます。
  • React.useState フックを使用して、コンポーネントの状態を管理することができます。

非制御コンポーネント

  • カスタムフック を使用して、状態の管理と値の更新をカプセル化することができます。
  • シンプルなコンポーネントの場合は、非制御コンポーネント を使用するのがおすすめです。

reactjs react-component


Reactコンポーネントに条件付きで属性を追加するベストプラクティス

1 三項演算子を使う3 フラグメントを使う1 className 属性2 style 属性条件付き属性のロジックを再利用したい場合は、カスタムフックを使うと便利です。上記以外にも、条件付き属性を追加する方法はありますか?条件付きで属性を追加する際の注意点は何ですか?...


React 17とTypeScript 2.3で実現するReact Childrenの型安全な開発

従来の関数コンポーネントの型定義は次のようでした。この場合、childrenプロパティはReactNode型でした。これは、文字列、React要素、その他のコンポーネントなど、あらゆる種類の値を受け取れることを意味します。しかし、これは型安全性においてあまり望ましくありません。...


Reactで発生する「Uncaught Invariant Violation: Rendered more hooks than during the previous render」エラーの徹底解説

このエラーが発生する主な原因は次のとおりです。条件付きレンダリング内でフックを使用すると、条件によってフックの数がレンダリングごとに変化する可能性があります。上記の例では、useEffect フックは count が 0 の場合のみレンダリングされます。しかし、setCount を呼び出すと count が 1 になり、useEffect フックがレンダリングされなくなります。...


React ファンクショナルコンポーネント開発における非同期処理の羅針盤:Async/Await の詳細ガイド

React ファンクショナルコンポーネントは、非同期処理を扱う際に async/await を活用することで、より読みやすく、メンテナンスしやすいコードを書くことができます。このガイドでは、async/await を用いた非同期処理の実装方法を、分かりやすく詳細に解説します。...


ReactJSで「Switch」コンポーネントを使用する際に発生するエラー「Attempted import error: 'Switch' is not exported from 'react-router-dom'」の原因と解決策とは?

エラー発生時の状況:プロジェクトでreact-router-domを使用しているコード内でSwitchコンポーネントを使用しようとしているコンソールに以下のエラーメッセージが表示されるエラーの原因:Switchコンポーネントは、react-router-domバージョン5...


SQL SQL SQL SQL Amazon で見る



React Select で ref と setValue メソッドを使用してデフォルト値を設定する

例この例では、defaultValue プロパティに { value: '2', label: '値2' } オブジェクトを渡しています。これは、コンポーネントが最初にレンダリングされたときに "値2" オプションが選択されることを意味します。