如何用Hooks扩展运算符存储Material-UI Autocomplete键值并用于API查询
问题解决与代码修正
原代码核心问题
setFilter是异步操作,直接在handleChange里console.log(filter)无法获取最新值- Autocomplete组件存在重复设置options、value绑定错误、id重复的问题
- 直接将filter对象拼入URL会导致格式错误,需转换为标准查询字符串
handleChange中value.value是错误写法(当options为字符串数组时,选中的value就是字符串本身)
修正后的完整代码
1. 状态与事件处理
import { useState, useEffect } from 'react'; import { Autocomplete, TextField } from '@mui/material'; const EquipmentFilter = () => { // 初始化状态用空字符串,而非空格 const [filter, setFilter] = useState({ DEPARTMENT: "", Hosp_Name: "", Equip_Name: "", Status: "", Equip_Id: "" }); // 处理选择变化:用函数式更新确保拿到最新状态,直接赋值选中值 const handleChange = (event, value) => { setFilter(prevState => ({ ...prevState, [event.target.name]: value || "" })); }; // 监听filter变化,打印最新值和转换后的查询字符串 useEffect(() => { console.log("当前筛选条件:", filter); // 转换为标准查询字符串格式 const queryString = new URLSearchParams(filter).toString(); console.log("查询字符串:", queryString); }, [filter]); // 发起API请求的示例函数 const fetchEquipments = async () => { // 过滤空值字段,避免无效参数 const validFilters = Object.fromEntries( Object.entries(filter).filter(([_, val]) => val.trim() !== "") ); const queryString = new URLSearchParams(validFilters).toString(); const apiUrl = `http://192.168.16.118:4000/equipments?${queryString}`; try { const res = await fetch(apiUrl); const data = await res.json(); console.log("后端返回数据:", data); // 这里处理拿到的数据 } catch (err) { console.error("请求失败:", err); } };
2. 修正后的Autocomplete组件
保证每个组件id唯一、value绑定对应filter字段、options不重复设置:
return ( <div style={{ display: "flex", gap: "16px", padding: "16px" }}> <Autocomplete disablePortal id="department-combo" name="DEPARTMENT" options={dept.map(opt => opt.DEPARTMENT || "").filter(Boolean)} value={filter.DEPARTMENT} sx={{ width: 200 }} renderInput={(params) => <TextField {...params} label="科室" />} onChange={handleChange} /> <Autocomplete disablePortal id="equip-name-combo" name="Equip_Name" options={equip.map(opt => opt.EQUIPMENT_NAME || "").filter(Boolean)} value={filter.Equip_Name} sx={{ width: 200 }} renderInput={(params) => <TextField {...params} label="设备名称" />} onChange={handleChange} /> <Autocomplete disablePortal id="hosp-name-combo" name="Hosp_Name" options={hospname.map(opt => opt.Unit_Name || "").filter(Boolean)} value={filter.Hosp_Name} sx={{ width: 150 }} renderInput={(params) => <TextField {...params} label="医院" />} onChange={handleChange} /> <Autocomplete disablePortal id="status-combo" name="Status" options={status.map(opt => opt.EQUIP_STATUS || "").filter(Boolean)} value={filter.Status} sx={{ width: 150 }} renderInput={(params) => <TextField {...params} label="状态" />} onChange={handleChange} /> <Autocomplete disablePortal id="equip-id-combo" name="Equip_Id" options={equipid.map(opt => opt.EQUIPMENT_ID || "").filter(Boolean)} value={filter.Equip_Id} sx={{ width: 150 }} renderInput={(params) => <TextField {...params} label="设备ID" />} onChange={handleChange} /> {/* 触发查询的按钮 */} <button onClick={fetchEquipments}>查询设备</button> </div> ); }; export default EquipmentFilter;
关键说明
- 异步状态更新:必须通过
useEffect监听filter变化才能获取最新值,setFilter不会立刻更新状态 - 查询字符串转换:
URLSearchParams自动将对象转为key=value&key2=value2的标准格式,同时处理特殊字符编码 - 空值过滤:请求前过滤空字段,避免后端收到无效参数
- Autocomplete规范:每个组件id唯一,value与状态字段绑定,options仅设置一次并过滤空值
内容的提问来源于stack exchange,提问作者Lakhvir Singh
相关产品推荐
相关产品推荐

