🗒️

現場で使えるReactコンポーネント第2弾 InputText編

2023/04/18に公開

はじめに

本記事は現場で使えるReactコンポーネント第二弾の記事です。
(今回からタイトルをこっそり変更しました)

第一弾のButton編の記事はこちら

InputText.tsx

今回はInputTextを作成しました。

まず、InputTextとはinputタグでテキスト入力を行うためのコンポーネントのことです。見た目はこんな感じ
InputText

開発環境は以下の通りです。

node.js v18.14.2
react v18.2.0
typescript v4.9.5

実際に作成したコードがこちらです↓↓

InputText.tsx
import { forwardRef, InputHTMLAttributes, useState } from "react";
import classNames from "classnames";
import styles from "./InputText.module.css";
import { FaEye, FaEyeSlash } from "react-icons/fa";

interface InputTextProps extends InputHTMLAttributes<HTMLInputElement> {
  hasError?: boolean;
  hasPasswordMask?: boolean;
}

const InputText = forwardRef<HTMLInputElement, InputTextProps>(
  (
    { hasError = false, hasPasswordMask = false, className, type, ...props },
    ref
  ) => {
    const [unmasking, setUnmasking] = useState(false);

    const inputText = (
      <input
        ref={ref}
        className={classNames(
          styles.inputText,
          hasError && styles.error,
          hasPasswordMask && styles.passwordMask,
          className
        )}
        type={unmasking ? "text" : type}
        {...props}
      />
    );

    if (hasPasswordMask) {
      return (
        <div className={styles.maskInput}>
          {inputText}
          <button
            className={styles.maskButton}
            type="button"
            onClick={() => setUnmasking((s) => !s)}
          >
            {unmasking ? <FaEye /> : <FaEyeSlash />}
          </button>
        </div>
      );
    }

    return inputText;
  }
);

export default InputText;

実装のポイントは以下の通りです。

  1. forwardRefでコンポーネントを作成した点
  2. パスワードの表示非表示を切り替えられる点

第一弾から引き続き、以下の内容は意識して実装を行なっています。

  • propsはInputHTMLAttributesを拡張する
  • 親からもスタイルを変更できるようにする
  • 汎用コンポーネントではmarginを指定しない

1. forwardRefでコンポーネントを作成した点

Reactの開発ではreact-hook-formという入力フォームの処理をいい感じにしてくれるライブラリを使うことが頻繁にあります。そのライブラリではDOM操作を行うため、forwardRefを用いてinputタグのコンポーネント作成しました。
https://react-hook-form.com/get-started

2. パスワードの表示非表示を切り替えられる点

propsでtype="password"hasPasswordMaskを渡すことでパスワードの表示非表示が正しく動作します。
パスワードの表示非表示のために別コンポーネントを作成しても良いのですが、個人的には1つにまとめた方が使いやすいと思ったので実装しました。

実際にコンポーネントを使ってみる

第一弾のButtonと今回のInputTextを使って簡単なログインフォームを作成しました。

作成したログインフォームの見た目はこんな感じ

コードはこんな感じ
https://github.com/shuuuu10-01/useful-react-components/blob/main/src/components/InputText/InputText.stories.tsx#L29-L97

今回の実装では、InputTextを使うことが目的だったのでそのまま使いました。
InputTextとlabelタグを組み合わせたコンポーネントを作成してもいいと思います。

Storybookをデプロイしてあるので実際に触ってみてください。

最後に

ここまで読んでいただきありがとうございます。
前回からかなり時間が空いてしまいましたが、引き続きひっそりとゆっくり続けていきたいと思います。
次回はTabコンポーネントを予定しています。

Discussion