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

如何修改传入CustomInput的Form.Control的type属性实现密码显隐功能

问题根源

你直接将已实例化的<Form.Control> React元素作为prop传入CustomInput,React元素是不可变对象,无法直接修改其属性,所以你直接给formControl.type赋值的写法不会生效。你之前在父组件定义状态绑定type也不生效,是因为父组件的状态和CustomInput内部的状态完全独立,没有关联。


正确实现方案

1. 修改CustomInput.js

使用React.cloneElement克隆传入的formControl元素,动态覆盖type属性即可,同时不要直接修改传入的rightAddon prop(props为只读,直接修改会引发副作用),改为生成新的配置对象:

import { Icon } from '../Icon'
import { useState, cloneElement } from 'react'

export const CustomInput = ({ formControl, rightAddon: rawRightAddon, passwordEye }) => {
  const [inputType, setInputType] = useState("password")
  const [showPassword, setShowPassword] = useState(false)
  
  const togglePasswordEye = () => {
    setInputType(prev => prev === 'text' ? 'password' : 'text')
    setShowPassword(prev => !prev)
  }

  // 生成右侧附加配置,不修改原始props
  const rightAddon = passwordEye ? {
    ...rawRightAddon,
    icon: showPassword ? 'eye' : 'eye-slash',
    onClick: togglePasswordEye,
    clickable: true
  } : rawRightAddon

  // 克隆输入框组件,密码模式下覆盖type属性
  const processedFormControl = passwordEye 
    ? cloneElement(formControl, { type: inputType })
    : formControl

  return (
    <div>
      {processedFormControl}
      {rightAddon && (
        <span className={`password-eye ${passwordEye || rightAddon.clickable ? 'cursor-pointer' : ''}`} onClick={rightAddon.onClick}>
          <Icon name={rightAddon.icon} />
        </span>
      )}
    </div>
  )
}

2. 修改LogIn.js

你不需要再在父组件维护密码显示相关的状态(inputType、showPassword、togglePasswordEye都可以删掉),直接按你期望的写法调用即可:

import Form from 'react-bootstrap/Form'
import { CustomInput } from '../CustomInput'

// 省略其他无关代码...
<CustomInput 
  passwordEye 
  rightAddon={{icon: "eye"}} 
  formControl={
    <Form.Control
      className={`form-control form-control-lg ${errors.password ? 'input-error' : ''}`}
      placeholder="Enter your password"
      type="password"
      name="password"
      autoComplete="current-password"
      tabIndex={2}
      {...register("password", {
        required: "Password is required",
        minLength: {
          value: 6,
          message: "Password should be more than 6 characters"
        }
      })}
    />
  } 
/>

实现原理

React.cloneElement可以接收一个已有的React元素作为第一个参数,第二个参数传入需要覆盖的新props,返回一个合并了新属性的新元素,以此实现动态修改传入组件属性的需求。所有密码显隐的逻辑都封装在CustomInput内部,完全符合你仅添加passwordEye属性即可启用功能的目标。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:36:06