React多选下拉框搜索后选中状态异常问题排查
带搜索功能的多选下拉框组件异常问题
我正在开发一个带搜索功能的多选下拉框组件,大部分功能正常,但存在一个问题:
- 初始选择“1”和“3”后,输入框能正确展示已选状态
- 当搜索包含数字“4”的选项时,选项“4”会被自动选中,可我实际只选了“1”和“3”
以下是组件核心代码(已移除Tailwind样式及无关函数):
"use client" import React, { useEffect, useId, useState } from "react" export default function Cscheckdropdown(props: Props) { const inputText = useId() const inputSearch = useId() const [value, setValue] = useState < string[] > ([]) const [searchValue, setSearchValue] = useState("") const [optionsFiltered, setOptionsFiltered] = useState(props.options.map((option) => { return option })) const handleSetValue = (e: React.MouseEvent<HTMLInputElement>) => { const valor = e.currentTarget.value if (!value.includes(valor)) { setValue([...value, valor]) } else if (value.includes(valor)) { setValue(value.filter(v => v != valor)) } } useEffect(() => { setOptionsFiltered( props.options.filter((x) => { if (x.includes((searchValue))) { return x } }) ) }, [props.options, searchValue]) return (<> <div> <input id={inputSearch} name={props.name + "_inputSearch"} type="text" onChange={(e) => { setSearchValue(e.currentTarget.value) }} value={searchValue} /> </div> { optionsFiltered.map((option, index) => { return ( <div key={index}> <label htmlFor={inputText + index}> <input type="checkbox" id={inputText + index} name={props.name} value={option} onClick={handleSetValue} /> {option} </label> </div> ) }) } </>) }
问题根源
- 复选框未受控:代码里的复选框没有绑定
checked属性,React无法跟踪其选中状态。当搜索过滤导致组件重渲染时,浏览器会复用DOM元素,出现状态错乱。 - key值不合理:使用数组
index作为key,过滤后选项顺序变化时,React会错误复用旧组件的状态,导致未选择的选项被自动选中。
修复方案
1. 让复选框成为受控组件
给每个复选框添加checked属性,绑定到已选数组value是否包含当前选项:
<input type="checkbox" id={inputText + option} name={props.name} value={option} onClick={handleSetValue} checked={value.includes(option)} // 新增:绑定选中状态 />
2. 替换key值为唯一标识符
将key从index改为option(确保所有选项值唯一),避免React复用错误的组件状态:
<div key={option}> {/* 替换index为option */} <label htmlFor={inputText + option}> {/* 复选框代码 */} </label> </div>
3. 简化过滤逻辑(可选)
原过滤函数可以简化为直接返回布尔值,代码更简洁:
useEffect(() => { setOptionsFiltered( props.options.filter(x => x.includes(searchValue)) ) }, [props.options, searchValue])
内容的提问来源于stack exchange,提问作者Thiago Barboza
相关产品推荐
相关产品推荐

