見出し画像

フロントエンド初心者が手始めにパスワード入力時の表示・非表示機能を実装してみた

この記事は「株式会社メンバーズ Jamstack研究会主催 Advent Calendar2023」の21日目の記事です。


はじめに

こんにちは!株式会社メンバーズの中野です。

この度未経験エンジニアとして入社して3年目になるこの僕が、初めてガッツリフロントエンドを触ることになったので、今回は皆さんもよく目にするパスワード入力時の表示・非表示機能を実装したので紹介します。

今回はReactで実装を行いました。また、MUI(Material UI)も使用しています。

そもそもパスワード表示・非表示機能とは?

ここまで何となく読んでみたもののパスワード表示・非表示機能と聞いてあまりピンと来ていない方もいるかと思います。
「百聞は一見に如かず」なのでとりあえずは以下の画像をご覧ください。

画像の通り、パスワード表示・非表示機能とは、目玉マークをクリックするとパスワードが表示されたり非表示になったりするような機能のことを指しています。

いざ、実装へ!

目玉アイコンのインポート

まずは入力フォーム内に表示させる目玉アイコンのインポートを行います。今回はMUIの目玉アイコンを使用します。

// 表示アイコン
import VisibilityIcon from "@mui/icons-material/Visibility";

// 非表示アイコン
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";

目玉アイコンクリック時の動きの制御

次に目玉アイコンをクリックした時の動きの制御を行います。目玉アイコンが表示アイコンになっている時にクリックすると、パスワードが表示され、目玉アイコンは非表示アイコンになる必要があります。
今回はReactを使用しているので、ReactでuseStateを使用します。useStateとは、関数コンポーネントで状態を管理するものです。

// パスワード表示制御用のstate
const [password, setPassword] = useState(false);

// パスワード入力時のトグル
const togglePassword = () => {
        setPassword(!password);
}

これで下準備は完成です。

実際に入力フォームに埋め込む

では、実際に入力フォームに埋め込んでいきます。
まずは入力したパスワードを表示するかマスク(非表示)するかの処理を'type'属性で記述します。

<TextField
    id="password"
    type={password ? 'text' : 'password'}
    name="password"
    value={data.password}
    autoComplete="new-password"
    onChange={(e) => setData("password", e.target.value)}
    placeholder="英数字混在 8 桁以上で作成してください…"
    fullWidth
    required
    sx={
    .
    .
    .

こちらは三項演算子を使用しています。
これは'password'という変数が'true'であればtextタイプ、'false'であればpasswordタイプになるという処理です。
textタイプであれば入力したパスワードを表示させ、passwordタイプでは非表示にさせます。
また、先ほどの下準備で'useState(false)'と定義したことによって、初期状態はfalse、つまりpasswordタイプなのでパスワードは非表示となっています。

次に目玉アイコンの処理をInputPropsを使用して記述します。

<TextField
    id="password"
    type={password ? 'text' : 'password'}
    name="password"
    value={data.password}
    autoComplete="new-password"
    onChange={(e) => setData("password", e.target.value)}
  placeholder="大文字、小文字、英数字混在 8 桁以上で作成してください…"
  fullWidth
  required
  sx={
      [
         {bgcolor: '#ffffff', marginTop: '4px', borderRadius: 5},
           {"&&& .MuiOutlinedInput-root": {
             paddingRight: 1,
           flexWrap: "nowrap",
           borderRadius: 5,
           color: "inherit",
           fontFamily: "inherit",
           "&:not(.Mui-focused) fieldset": {
               borderColor: "transparent",
           },
           "& fieldset": {
                borderWidth: 1,
            },
        }},
         ]
    }
  inputProps={{
      style:
        {
          padding: '8px 12px',
        }
   }}
  InputProps={{
      endAdornment:
        <InputAdornment position="end">
          {password ? (
            // 表示
          <VisibilityOffIcon
              onClick={togglePassword}
            className="Password__visual"
            sx={{
                ":hover": {
                  cursor: "default",
              }
                }}
                />
            ) : (
            // 非表示
          <VisibilityIcon
              onClick={togglePassword}
            className="Password__visual"
            sx={{
                ":hover": {
                  cursor: "default",
                }
                   }}
              />
             )}
          </InputAdornment>
    }}
/>

これも一見わかりにくいですが三項演算子を使用しています。
変数'password'が'true'の時に非表示アイコン、'false'の時に表示アイコンを使用する形になっています。
また、下準備のところで'password'変数の'true'と'false'を入れ替えるトグルの処理を記述しています。'onClick={togglePassword}'を使用することでクリックしたときに'password'変数の'true'と'false'を入れ替え、目玉アイコンの表示も入れ替わるようになっています。

ここで一つ疑問が・・・

実装している最中に一つ疑問が生まれました。それは実際に入力したパスワードの表示と目玉アイコンをどういうふうにリンクさせるかです。これだけ聞いても「???」となる方がたくさんいるとは思いますが、下記の2つの画像のように、例えば目玉アイコンが表示状態の時、入力した実際のパスワードはどのようになっているべきかということです。


クリックした後の状態を表す目玉アイコン


クリックする前の状態を表す目玉アイコン

実際に色々調べてみましたが、どちらのパターンもたくさん見つかったので、結論どちらでも良さそうです。
ですが天下のGoogleさんを調べると、上記画像1枚目の「クリックした後の状態を表す目玉アイコン」を使用していたので、今回はGoogleさんと同じ状態のものを実装しました。

完成!

これで完成しました!以下がコードと実際の画像になります。

import { Box, InputAdornment, TextField } from "@mui/material";
import VisibilityIcon from "@mui/icons-material/Visibility";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";

export default function Register({
    // パスワード表示制御用のstate
    const [password, setPassword] = useState(false);

    // パスワード入力時のトグル
    const togglePassword = () => {
        setPassword(!password);
    }

    return (
      <>
            <Box>
        <div className="mt-4">
            <InputLabel
                htmlFor="password"
                value="パスワード"
            />

            <TextField
                id="password"
                type={password ? 'text' : 'password'}
                name="password"
                value={data.password}
                autoComplete="new-password"
                onChange={(e) =>
                    setData("password", e.target.value)
                }
                placeholder="大文字、小文字、英数字混在 8 桁以上で作成してください…"
                fullWidth
                required
                sx={
                    [
                        {bgcolor: '#ffffff', marginTop: '4px', borderRadius: 5},
                        {"&&& .MuiOutlinedInput-root": {
                            paddingRight: 1,
                            flexWrap: "nowrap",
                            borderRadius: 5,
                            color: "inherit",
                            fontFamily: "inherit",
                            "&:not(.Mui-focused) fieldset": {
                                borderColor: "transparent",
                            },
                            "& fieldset": {
                                borderWidth: 1,
                            },
                        }},
                    ]
                }
                inputProps={{
                    style:
                        {
                            padding: '8px 12px',
                        }
                }}
                InputProps={{
                    endAdornment:
                        <InputAdornment position="end">
                            {password ? (
                                // 表示
                                <VisibilityOffIcon
                                    onClick={togglePassword}
                                    className="Password__visual"
                                    sx={{
                                        ":hover": {
                                            cursor: "default",
                                        }
                                    }}
                                />
                            ) : (
                                // 非表示
                                <VisibilityIcon
                                    onClick={togglePassword}
                                    className="Password__visual"
                                    sx={{
                                        ":hover": {
                                            cursor: "default",
                                        }
                                    }}
                                />
                            )}
                        </InputAdornment>
                }}
             />
                 </div>
             </Box>
        </>
    );
}
パスワード非表示


パスワード表示

これで自分が入力したパスワードが可視化されるようになりました!

おわりに

今回はReactとMUIを使用してパスワード表示・非表示機能を実装してみました。
フロントエンドを初めて触ったのでもう少し綺麗なコードが書けそうですが…今回でフロントエンドの楽しさを知ってしまったので、これからもっと勉強していこうと思います。
お付き合いいただきありがとうございました!


この記事が気に入ったらサポートをしてみませんか?