I have trouble toggling an input type between password and text to show the password in the login form.
The functionality is that when clicking on the eye icon on the password input it should show the password in plain text but this is not happening.
Technically speaking I am trying to change the type of password input to text without success.
This is the code:
const [showPassword, setShowPassword] = useState(false)
const passwordRef = useRef<HTMLInputElement>(null);
const handleShowPassword = (ref: React.RefObject<HTMLInputElement>) => {
if (ref.current && ref.current.id === 'password') {
setShowPassword((prev) => !prev);
if (showPassword) {
ref.current!.type = "password";
console.log('passwordRef.current?.type: ', ref.current?.type); // password
} else {
ref.current!.type = "text";
console.log('passwordRef.current?.type: ', ref.current?.type); // text
}
}
};
return (
<Container>
<BackgroundBox />
<FormBox>
{/* Password */}
<div className='auth-input-container login-password'>
<FaKey className="auth-icon" size='20px' />
<input
type="password"
id="password"
name="password"
placeholder="Enter password"
className="auth-input"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.password}
ref={passwordRef}
/>
{
showPassword ? <FaEyeSlash className="auth-icon-password-eye" onClick={() => handleShowPassword(passwordRef)} />
: <FaEye className="auth-icon-password-eye" onClick={() => handleShowPassword(passwordRef)} />
}
</div>
{formik.touched.password && formik.errors.password ? (
<div className="error-message">{formik.errors.password}</div>
) : null}
// and closing tags
When I log the types in handleShowPassword it actually shows text or password as it should bu in the end the actual passwordRef type is not ever changing to text but always stays text.
The strange thing is that if I use Vanilla JS instead of useRef :
const handleShowPassword = (ref: React.RefObject<HTMLInputElement>) => {
const DOMref = document.getElementById('password') as HTMLInputElement;
if (DOMref.id === 'password') {
console.log('DOMref: ', DOMref);
if (DOMref.type === 'password') {
DOMref.type = 'text'
} else {
DOMref.type = 'password'
}
}
};
This would work fine.
How come? How to fix this problem?
>Solution :
You can achieve this by conditionally setting the input type as so:
const [showPassword, setShowPassword] = useState(false)
const handleShowPassword = () => {
setShowPassword(!showPassword);
};
return (
<Container>
<BackgroundBox />
<FormBox>
{/* Password */}
<div className='auth-input-container login-password'>
<FaKey className="auth-icon" size='20px' />
<input
type={showPassword ? "text" : "password"}
id="password"
name="password"
placeholder="Enter password"
className="auth-input"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.password}
ref={passwordRef}
/>
{
showPassword ? <FaEyeSlash className="auth-icon-password-eye" onClick={handleShowPassword} />
: <FaEye className="auth-icon-password-eye" onClick={handleShowPassword} />
}
</div>
{formik.touched.password && formik.errors.password ? (
<div className="error-message">{formik.errors.password}</div>
) : null}
// and closing tags