LoginSignup
4
8

More than 3 years have passed since last update.

【React】入力用コンポーネント作成の基本

Posted at

入力コンポーネントを作ろう!

入力するのでコンポーネント内部に入力されたデータを保持しないと。
こんな感じかな?

import React from "react";

export const IncorrectTextBox = (props: Props) => {
  const [value, setValue] = React.useState("");

  return (
    <label style={{ display: "block" }}>
      {`${props.label} `} 
      <input
        value={value}
        onChange={event => setValue(event.target.value)} />
    </label>
  );
}

使うときはこんな感じだね。

const App = () => {
  return (
    <div style={{ maxWidth: 400, margin: "auto", padding:50 }}>
      <IncorrectTextBox label="Input your fisrt name." />
      <IncorrectTextBox label="Input your last name." />
    </div>
  )
}

image.png

ちゃんと入力できてるみたい!完璧!

入力を確認するエリアを用意したい?

入力確認をするためにフルネームを表示する要素を用意しよう!

const App = () => {
  return (
    <div style={{ maxWidth: 400, margin: "auto", padding:50 }}>
      <IncorrectTextBox label="Input your first name." />
      <IncorrectTextBox label="Input your last name." />
      <div>{`${firstName} ${lastName}`}</div>
    </div>
  )
}

あとはfirstNamelastNameさえ取れれば表示できる!

IncorrectTextBoxコンポーネントからそれぞれの入力値を取得するにはどうしたらいいだろうか?

どうしたらいいだろうか?

どうしたらいいだろうか…?





取れません。

制御されたコンポーネントにしましょう

ユーザーの入力を受け付けるコンポーネントの基本は

  • 入力値をpropsで受け付ける
  • 変更があったら実行する関数をpropsで受け付ける

の2点です。各々で状態を持つのではなく、そのコンポーネントを利用する側に制御されるように設計します。

例えばフリーのテキスト入力ならば下のようになります。

interface RevolutionaryTextBoxProps {
  value: string,
  onChange: (value: string) => void,
}

export const RevolutionaryTextBox = (props: RevolutionaryTextBoxProps) => {
  return (
    <input
      type="text"
      value={props.value}
      onChange={event => props.onChange(event.target.value)} />
  );
}

TypeScriptなのでinterfaceを定義しています。
propsstring型の引数valueを受け取ります。そして、ユーザーが入力するたびに入力後の新規の値を渡して実行する関数を受け取り、実際にユーザーの入力のたびに実行されるようにしておきます。

そしてこの入力コンポーネントを利用する側がstateを管理します。

const App = () => {
  const [firstName, setFirstName] = React.useState("");
  const [lastName, setLastName] = React.useState("");

  return (
    <div style={{ maxWidth: 750, margin: "20px auto" }}>
      <label>
        FirstName
        <RevolutionaryTextBox
          value={firstName}
          onChange={setFirstName} />
      </label>
      <label>
        LastName
        <RevolutionaryTextBox
          value={lastName}
          onChange={setLastName} />
      </label>
      <div>{`${firstName} ${lastName}`}</div>
    </div>
  )
}

image.png
("Revolutionary"な背景色にしました。笑)

string型の入力を受け付ける簡単なコンポーネント例を出しましたが、これがnumber型の数値入力でもboolean型のトグルスイッチでもスライドバーでもDatePickerでも基本は同じです。
props経由で入力対象のデータ型の値と、入力後に新規の値を引数に渡して実行される関数を受け取るようなコンポーネントにします。

こうすることで、例えば他の入力コンポーネントの値によって目的の入力コンポーネントも変更される、というようなフォームも実装することができます。

const App = () => {
  const [firstName, setFirstName] = React.useState("");
  const [lastName, setLastName] = React.useState("");

  return (
    <div className="container" style={{ maxWidth: 750, margin: "20px auto" }}>
      <label>
        FirstName
        <RevolutionalyTextBox
          value={firstName}
          onChange={value => {
            setFirstName(value);
            setLastName(value);  // setLastName()も同時に呼び出す
          }} />
      </label>
      <label>
        LastName
        <RevolutionalyTextBox
          value={lastName}
          onChange={setLastName} />
          <div>{`${firstName} ${lastName}`}</div>
      </label>
    </div>
  )
}

タイトルなし.gif

終わり

わたくしなんと9ヶ月の無職期間を終えて4月よりWeb企業に就職しました🎊
念願だったReactとTypeScriptを業務で扱えることになりました🎉

同様に新しくReactを始めた方がいらっしゃると思います。
そんな方に読んでいただければ幸いです。

4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8