You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React密码显隐切换功能仅单个输入框生效问题排查

问题描述

在React项目中实现密码、确认密码两个输入框的显隐切换功能时,点击切换按钮仅第一个密码输入框的显隐状态生效,第二个输入框无法正常切换密码/明文展示状态。
问题效果参考:
密码显隐切换异常效果
原始功能代码如下:

import React from "react";

function ShowHidePassword(){
    const [values, setValues] = React.useState({
        password: "",
        passwordConf: "",
        showPassword: true,
    });
    const clickShowPassword = (event) => {
        setValues({ ...values, showPassword: !values.showPassword });
        event.preventDefault();
    };
    
    const passwordChange = (prop) => (event) => { setValues({ ...values, [prop]: event.target.value }); };
    const mouseDownPassword = (event) => { event.preventDefault(); };
    
    return (
        <div>
            <input
                type={values.showPassword ? "text" : "password"}
                onChange={passwordChange("password")}
                value={values.password} id="signup-password"
                placeholder="PASSWORD"
            />
            <input
                type={values.showPassword ? "text" : "passwordConf"}
                onChange={passwordChange("passwordConf")}
                value={values.passwordConf} id="signup-password-confirm"
                placeholder="CONFIRM PASSWORD"
            />
            <br/>
            <button className="hide-password2" onClick={clickShowPassword} onMouseDown={mouseDownPassword}>
                {values.showPassword===false? <i className="bi bi-eye-slash"></i> :<i className="bi bi-eye"></i> } Show Password
            </button>
        </div>
    );

};

export default ShowHidePassword;
问题原因
  • 核心错误:确认密码输入框的type属性判断逻辑写错,隐藏状态分支返回的是passwordConf(这是存储确认密码输入值的state字段,不是合法的输入框类型),浏览器遇到不识别的input type会默认渲染为明文文本输入,导致切换看起来对第二个框无效。
  • 潜在隐患:状态更新直接取闭包内的values值,React状态更新为异步批量执行,连续触发更新时可能拿到旧的状态值,导致逻辑异常。
修复方案

修正确认密码框的type判断逻辑,同时将状态更新改为函数式写法规避闭包旧值问题,修复后完整代码如下:

import React from "react";

function ShowHidePassword(){
    const [values, setValues] = React.useState({
        password: "",
        passwordConf: "",
        showPassword: true,
    });
    const clickShowPassword = (event) => {
        setValues(prev => ({ ...prev, showPassword: !prev.showPassword }));
        event.preventDefault();
    };
    
    const passwordChange = (prop) => (event) => { 
        setValues(prev => ({ ...prev, [prop]: event.target.value })); 
    };
    const mouseDownPassword = (event) => { event.preventDefault(); };
    
    return (
        <div>
            <input
                type={values.showPassword ? "text" : "password"}
                onChange={passwordChange("password")}
                value={values.password} 
                id="signup-password"
                placeholder="PASSWORD"
            />
            <input
                type={values.showPassword ? "text" : "password"}
                onChange={passwordChange("passwordConf")}
                value={values.passwordConf} 
                id="signup-password-confirm"
                placeholder="CONFIRM PASSWORD"
            />
            <br/>
            <button className="hide-password2" onClick={clickShowPassword} onMouseDown={mouseDownPassword}>
                {values.showPassword===false? <i className="bi bi-eye-slash"></i> :<i className="bi bi-eye"></i> } Show Password
            </button>
        </div>
    );

};

export default ShowHidePassword;

拓展:如果需要两个密码框独立控制显隐,只需要将showPassword拆分为showPassword、showPasswordConf两个独立state字段,分别绑定对应输入框的type属性和切换按钮事件即可。

内容的提问来源于stack exchange,提问作者jolyne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:09:10