React中MultiSelect多选值分存不同数组的功能异常排查
问题修复:MultiSelect多选值按层级存入对应数组
需求说明
希望在MultiSelect组件中选择值后,将每个多选组件的选中值存入不同数组,默认数组为空,最终形成类似{1:[1,2],2:[2,3]}的结构。
现有代码问题
你提供的代码存在几个关键问题导致多选功能失效:
- MultiSelect组件的
value和onChange属性被注释,无法与父组件状态联动 - 初始化选中值状态时逻辑错误,没有为每个层级的set分配空数组
- 状态更新后的同步打印无法获取最新值
- 两个输入控件(下拉选择框和数字输入框)绑定了同一个处理函数,逻辑混乱
修复方案
- 恢复MultiSelect的联动属性:取消
value和onChange的注释,让组件能读取选中值并触发状态更新 - 修正状态初始化逻辑:在切换层级时,为每个set初始化空数组,确保结构正确
- 调整状态更新方式:修正
handleMultiSelectChange中的对象嵌套更新逻辑,保证每个set的选中值正确存入对应位置 - 正确打印更新后的状态:使用
useEffect监听状态变化,而非同步打印 - 优化列表key值:用
setNumber作为列表key,避免index作为key引发的渲染异常
修正后的完整代码
import React, { useState, useEffect } from 'react'; import { fetchApprovalItemType, fetchAllStaff } from './data'; import Set from './set'; import MultiSelect from './MultiSelect'; const AddApprovalItems = () => { const [items, setItems] = useState([]); const [staffs, setStaff] = useState([]); const [approvalItemLevel, setApprovalItemLevel] = useState(''); const [selectedOptions, setSelectedOptions] = useState({}); const [sets, setSets] = useState([]); useEffect(() => { const fetchData = async () => { const item = await fetchApprovalItemType(); setItems(item); }; const fetchStaff = async () => { const staff = await fetchAllStaff(); setStaff(staff); }; fetchData(); fetchStaff(); }, []); // 监听选中值变化,打印最新状态 useEffect(() => { console.log('最新选中值:', selectedOptions); }, [selectedOptions]); const handleApprovalLevelChange = (e) => { const level = parseInt(e.target.value); setApprovalItemLevel(level); // 创建对应数量的set const newSets = Array.from({ length: level }, (_, index) => index + 1); setSets(newSets); // 初始化当前层级的选中值:每个set对应空数组 setSelectedOptions((prevOptions) => ({ ...prevOptions, [level]: newSets.reduce((acc, num) => { acc[num] = []; return acc; }, {}) })); }; const handleMultiSelectChange = (selected, setNumber) => { setSelectedOptions((prevOptions) => ({ ...prevOptions, [approvalItemLevel]: { ...prevOptions[approvalItemLevel], [setNumber]: selected.map(option => option.value), }, })); }; const onSubmit = (e) => { e.preventDefault(); console.log('提交的选中值:', selectedOptions); }; return ( <div className="flex justify-center items-center lg:mt-[5%] mt-[20%]"> <div className="card lg:w-1/2 w-[80%] rounded-[10px]"> <div className="p-6"> <div className="flex"> <h4 className="mb-5 uppercase dark:text-gray-300">Add Home Ownership</h4> </div> <form className="px-10"> <div className="mb-3"> <label className="block mb-2 font-semibold" htmlFor="approvalItemLevel"> Approval Item Type </label> <div> <select id="approvalItemLevel" className="form-select form-select-sm" onChange={handleApprovalLevelChange} value={approvalItemLevel} > <option value="">Select Approval Item Level</option> {items.map((it, idx) => ( <option key={idx} value={it}>{it}</option> ))} </select> </div> </div> <div className="mb-3"> <label className="block mb-2 font-semibold" htmlFor="approvalItemType"> Approval Item level </label> <div> <input type="number" id="approvalItemType" name="approvalItemType" className="form-input w-full placeholder:text-gray-400" onChange={handleApprovalLevelChange} value={approvalItemLevel} /> </div> </div> {/* 渲染生成的set */} <div className="mb-3"> {sets.map((setNumber) => ( <div key={setNumber}> <Set /> <MultiSelect option={staffs.map((staff) => ({ label: staff.email, value: staff.id, }))} value={selectedOptions[approvalItemLevel]?.[setNumber] || []} onChange={(selected) => handleMultiSelectChange(selected, setNumber)} /> </div> ))} </div> <button type="submit" className="btn bg-primary/90 text-white hover:bg-primary" onClick={onSubmit}> Submit </button> </form> </div> </div> </div> ); }; export default AddApprovalItems;
关键修复点说明
- 恢复MultiSelect的
value和onChange属性,实现组件与父状态的双向绑定 - 初始化
selectedOptions时,通过reduce为每个set生成空数组,确保结构符合{层级: {set1: [], set2: []}} - 使用
useEffect监听selectedOptions变化,确保打印的是最新状态 - 用
setNumber作为列表key,避免index作为key可能导致的组件渲染异常
内容的提问来源于stack exchange,提问作者Ayobami
相关产品推荐
相关产品推荐

