現場で使えるReactコンポーネント第2弾 InputText編
はじめに
本記事は現場で使えるReactコンポーネント第二弾の記事です。
(今回からタイトルをこっそり変更しました)
第一弾のButton編の記事はこちら
InputText.tsx
今回はInputTextを作成しました。
まず、InputTextとはinputタグでテキスト入力を行うためのコンポーネントのことです。見た目はこんな感じ
開発環境は以下の通りです。
node.js v18.14.2
react v18.2.0
typescript v4.9.5
実際に作成したコードがこちらです↓↓
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;
実装のポイントは以下の通りです。
-
forwardRef
でコンポーネントを作成した点 - パスワードの表示非表示を切り替えられる点
第一弾から引き続き、以下の内容は意識して実装を行なっています。
- propsは
InputHTMLAttributes
を拡張する - 親からもスタイルを変更できるようにする
- 汎用コンポーネントでは
margin
を指定しない
forwardRef
でコンポーネントを作成した点
1. Reactの開発ではreact-hook-form
という入力フォームの処理をいい感じにしてくれるライブラリを使うことが頻繁にあります。そのライブラリではDOM操作を行うため、forwardRef
を用いてinputタグのコンポーネント作成しました。
2. パスワードの表示非表示を切り替えられる点
propsでtype="password"
とhasPasswordMask
を渡すことでパスワードの表示非表示が正しく動作します。
パスワードの表示非表示のために別コンポーネントを作成しても良いのですが、個人的には1つにまとめた方が使いやすいと思ったので実装しました。
実際にコンポーネントを使ってみる
第一弾のButtonと今回のInputTextを使って簡単なログインフォームを作成しました。
コードはこんな感じ
今回の実装では、InputTextを使うことが目的だったのでそのまま使いました。
InputTextとlabelタグを組み合わせたコンポーネントを作成してもいいと思います。
Storybookをデプロイしてあるので実際に触ってみてください。
最後に
ここまで読んでいただきありがとうございます。
前回からかなり時間が空いてしまいましたが、引き続きひっそりとゆっくり続けていきたいと思います。
次回はTabコンポーネントを予定しています。
Discussion