react-select使用统一状态对象存储选中值绑定失效问题咨询
失效原因
你的原有逻辑是针对原生表单控件设计的,react-select的回调和值绑定逻辑和原生控件不同,导致失效:
- react-select的
onChange回调第一个参数是当前选中的option对象(多选时为数组),不是原生事件对象,无法通过e.target读取name和value属性 - react-select的
value属性需要和options数组中选项的结构({value, label}格式)匹配,你当前状态里存储的是空字符串,无法和选项匹配,导致选中状态无法显示 - 代码存在笔误:Division下拉的value错绑为
selectedValue.class,应为selectedValue.Division - 额外注意:你定义options时的禁用属性是
isdisabled全小写,react-select识别的禁用属性是驼峰格式isDisabled,小写不会生效
修改方案
1. 改造handleChange兼容两类控件
react-select的onChange回调第二个参数会返回包含组件name属性的元数据,我们可以通过这个参数区分触发源,同时兼容原生input和react-select:
const handleChange = (value, meta) => { // meta存在说明是react-select触发的变更 if (meta) { setSelectedValue(prev => ({ ...prev, // 这里如果需要存完整option对象就直接写[meta.name]: value || null // 现在的写法是只存option的value值,和你原有逻辑对齐 [meta.name]: value?.value || '' })) } else { // 原生input触发的变更 const { name, value: inputValue } = value.target setSelectedValue(prev => ({ ...prev, [name]: inputValue })) } }
2. 调整react-select的value绑定
因为我们在状态里存的是option的value字符串,需要匹配到对应完整对象传给react-select的value属性,以Program下拉为例:
<Select name="Program" options={Program} onChange={handleChange} // 从options中找到对应value的对象传给value value={Program.find(opt => opt.value === selectedValue.Program) || null} />
其余react-select组件按照同样逻辑修改value绑定即可,同时修正Division下拉的绑定笔误。
完整修改后代码
import { useState } from "react"; import Select from "react-select"; // 注意修正了isDisabled的驼峰写法 const Program = [ { value: "MSC", label: "MSC" }, { value: "MCA", label: "MCA", isDisabled: true // 修正为驼峰写法才会生效 }, { value: "BSC", label: "BSC" }, { value: "BCA", label: "BCA", isDisabled: true // 修正为驼峰写法才会生效 } ]; // 这里请补充你自己定义的Class、Division、MSCCourses数组 const Class = []; const Division = []; const MSCCourses = []; function Download() { const requestSelected = e => { e.preventDefault(); // Axios.post('http://localhost:5000/login', attend) // .then(res => { // alert(res.data.message) // }) console.log(selectedValue); }; const [selectedValue, setSelectedValue] = useState({ Program: "", Class: "", Division: "", Course: "", Datefrom: "", Datetill: "" }); const handleChange = (value, meta) => { if (meta) { setSelectedValue(prev => ({ ...prev, [meta.name]: value?.value || "" })); } else { const { name, value: inputValue } = value.target; setSelectedValue(prev => ({ ...prev, [name]: inputValue })); } }; return ( <form className="D Download" method="POST"> <p>Download Form:</p> <label className="D_programlabel">Select Program:</label> <Select name="Program" options={Program} onChange={handleChange} value={Program.find(opt => opt.value === selectedValue.Program) || null} /> <label className="D_classlabel">Select Class:</label> <Select name="Class" options={Class} onChange={handleChange} value={Class.find(opt => opt.value === selectedValue.Class) || null} /> <label className="D_divisionlabel">Select Division:</label> <Select name="Division" options={Division} onChange={handleChange} {/* 修正了绑定笔误 */} value={Division.find(opt => opt.value === selectedValue.Division) || null} /> <label className="D_courselabel">Select Course:</label> <Select name="Course" options={MSCCourses} onChange={handleChange} value={MSCCourses.find(opt => opt.value === selectedValue.Course) || null} /> <ul className="date_time-container"> <li> <label>From Date :</label> <input type="date" name="Datefrom" placeholder="Enter Date" onChange={handleChange} value={selectedValue.Datefrom} /> </li> <li> <label>Till Date :</label> <input type="date" name="Datetill" placeholder="Enter Time" onChange={handleChange} value={selectedValue.Datetill} /> </li> </ul> <br /> <ul className="browse_upload-container"> <li> <label>File :</label> <input type="file" className="upload" accept=".csv" required></input> <button type="submit" id="submit-file" class="btn btn-primary"> Download File </button> </li> <li> <input type="submit" value="Submit" onClick={requestSelected} /> </li> </ul> </form> ); } export default Download;
内容的提问来源于stack exchange,提问作者tonotcodeatnight
相关产品推荐
相关产品推荐

