You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Hooks扩展运算符存储Material-UI Autocomplete键值并用于API查询

问题解决与代码修正

原代码核心问题

  1. setFilter是异步操作,直接在handleChange里console.log(filter)无法获取最新值
  2. Autocomplete组件存在重复设置options、value绑定错误、id重复的问题
  3. 直接将filter对象拼入URL会导致格式错误,需转换为标准查询字符串
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 00:25:26