输入框结合下拉框选择失焦问题

react 输入框结合下拉框选择失焦问题

问题:每次输入名字后,点击空白处,发现并没有请求,但是点击控制台区域,就正常请求了。

 <Select
    style={{ width: 120, marginRight: 10 }}
    placeholder="选择姓名"
     value={item.userName}
     showSearch
     allowClear
     filterOption={(input, option) => 
         (option?.children as string).toLowerCase().indexOf(input.toLowerCase()) >= 0
     }

     onSearch={(val) => {
         console.log('搜索关键词:', val); // 打印搜索关键词
         setSearchValue(val)}} // 禁止动态添加选项
         
     searchValue={searchValue}
     onChange={(value) =>{
         onSelectName(value, item, i);
         setSearchValue(''); 
     }} 
     onBlur={(e) => Information(e, item, i)}
     onKeyDown={(e) => {
         if (e.keyCode === 13) {
         Information(e, item, i);
         }
     }}
     >
     {personNameOptions.map(option => (
         <Option key={option.value} value={option.value}>{option.label}</Option>
     ))}
   </Select>

解决:使用Dropdown组件+input组件

<Dropdown
      overlay={
         <Menu>
           {personNameOptions.map(option => (
             <Menu.Item 
               key={option.value} 
               onClick={() => {
                 onSelectName(option.value, item, i);
               }}
             >
               {option.label}
             </Menu.Item>
           ))}
         </Menu>
       }
       visible={visible}
       onVisibleChange={(v) => setVisible(v)}
     >
       <Input
         value={item.inputValue || ''}
         onChange={(e) => handleInputChange(e, i)}
         onBlur={() => handleInputConfirm(i)}
         onPressEnter={() => handleInputConfirm(i)}
       />
 </Dropdown>

总结

1. 状态管理方式不同

原始代码
使用全局的 searchValue 状态管理所有输入框的搜索值

输入框值通过 Select 组件的 searchValue 和 onSearch 控制

问题:所有输入框共享同一个状态,导致交互冲突

修改后代码
为每个信息项(InformationItem)添加独立的 inputValue 属性

每个输入框维护自己的状态,互不干扰

优势:避免状态共享导致的值覆盖问题

// 修改后的数据结构
interface InformationItem {
  // ...
  inputValue?: string; // 新增字段
}

2. 输入处理逻辑不同

原始代码
使用 Information 函数处理 blur 和 enter 事件

依赖全局 searchValue,容易丢失上下文

问题:点击空白处时可能无法正确获取当前输入值

修改后代码
使用独立的 handleInputChange 和 handleInputConfirm 函数

直接通过数组索引操作对应项的状态

优势:确保总能获取正确的输入值

typescript
// 修改后的处理函数
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>, i: number) => {
  const newInforMation = [...inforMation];
  newInforMation[i].inputValue = e.target.value;
  setInforMation(newInforMation);
};

const handleInputConfirm = (i: number) => {
  const value = inforMation[i]?.inputValue?.trim();
  if (value) onSelectName(value, inforMation[i], i);
};

3. 组件类型不同

原始代码
使用 Select 组件实现搜索选择

需要处理 onSearch、onChange、onBlur 等多个事件

修改后代码
改用 Input + Dropdown 组合

更直接地控制输入行为

优势:避免 Select 组件的一些默认行为干扰

jsx
{/* 修改后的输入组件 */}
<Dropdown
  overlay={/* 下拉菜单 */}
>
  <Input
    value={item.inputValue || ''}
    onChange={(e) => handleInputChange(e, i)}
    onBlur={() => handleInputConfirm(i)}
    onPressEnter={() => handleInputConfirm(i)}
  />
</Dropdown>

4. 数据持久化策略不同

原始代码
在 onBlur 和 onChange 中都会清空 searchValue

导致输入后值立即消失

修改后代码
不再自动清空输入值

仅在API成功返回后更新数据

优势:保留用户输入,体验更友好

typescript
// 修改后的API处理
getUserInfoByName(name: string, item: InformationItem, i: number) {
  api.getUserInfoByPersonNameApi({ personName: name })
    .then(res => {
      // 成功时更新数据但保留inputValue
      newInforMation[i] = {
        ...newInforMation[i],
        inputValue: name // 关键区别:保留输入值
      };
    })
    .catch(err => {
      // 错误时也保留输入值
    });
}

5. 类型安全性增强

修改后代码新增
明确定义 InformationItem 接口

所有状态操作都遵循TypeScript类型检查

优势:减少运行时错误

typescript
interface InformationItem {
  userId: string;
  userName: string;
  email: string;
  edit: boolean;
  belongResId?: string;
  inputValue?: string; // 新增
  isAdd?: boolean; // 新增
}
  1. 不可变数据实践
    修改后代码改进
    所有状态更新都先创建新数组

避免直接修改原状态

优势:符合React最佳实践

typescript
// 示例:添加新项
const addInformat = (i: number) => {
  const newInforMation = [...inforMation]; // 先复制
  newInforMation.splice(i + 1, 0, { 
    /* 新对象 */
  });
  setInforMation(newInforMation); // 再更新
};

总结对比表

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值