【React】パスワード表示・非表示機能を有するInputComponentを作る

2024年3月24日

ログイン画面や会員登録において、パスワードを入力する場面がありますが、その際に入力したパスワードを確認する機能のついたものがあります。それをReactのcomponentとして作成しましょう。

表示・非表示切り替え

HTMLのinputは、type属性でpasswordを指定すると、入力された内容を非表示とします。

index.html


<input type="password"/>
 
このtype属性を、useStateによって、passwordとtextとで相互に切り替えることで、パスワードの表示・非表示機能を実装します。

実装

styleはTailwindCSSによってあてるものとします。また、componentのpropsは、inputエレメントと同様のものが渡せるようにしておきます。

src/components/PasswordInput/index.tsx


import { useState } from "react" ;

type Props = React.InputHTMLAttributes<HTMLInputElement> ;

export const PasswordInput:React.FC<Props> = (props) => {
  const [showPW,setShowPW] = useState<boolean>(false) //true時はパスワードを表示する.

  return (
    <div
      className="flex justyfy-between gap-2"     
    >
      <input
        {...props}
        type={showPW ? "text" : "password"}
     />

     <button
       onClick={()=>{setShowPW(!showPW)}}
     >
     <>{showPW ? "非表示" : "表示"}</>
     </button>

    </div>
  )
}
  

これで、パスワードの表示・非表示機能を備えた入力フォームを実装できます。実際には表示・非表示ボタンを、iconにしたり、装飾を施したりすることになります。

使用例

ログインフォームで使用する場合、たとえば次のように使用します。

src/components/LoginForm/index.tsx


import { Controller, useForm } from "react-hook-form";
import { PasswordInput } from "@/src/components/PasswordInputForm";

type FormInput = {
  email: string;
  password: string;
};

export const LoginForm = () => {
  const form = useForm<FormInput>();

  const onSubmit = form.handleSubmit(async (data) => {
    const apiRes = await fetch("https://example.com/api/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data),
    });
  });

  return (
    <form onSubmit={onSubmit}>
      <Controller
        name="email"
        control={form.control}
        render={({ field }) => (
          <>
            <label>Email</label>
            <input type="email" {...field} placeholder="user@example.com" />
          </>
        )}
      />

      <Controller
        name="password"
        control={form.control}
        render={({ field }) => (
          <>
            <label>Password</label>
            <PasswordInput placeholder="英数字8文字以上32文字未満" {...field} />
          </>
        )}
      />
    </form>
  );
};