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
相关产品推荐
相关产品推荐

