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

React省市级联下拉框无数据显示问题求助

省市级联下拉框无内容问题修复

问题核心原因

你的代码存在4个关键问题导致城市下拉框无内容:

  1. 省份下拉框未绑定正确value:渲染省份选项时只设置了显示文本,未将value绑定为对应省份的key(如banten),导致selected存储的是省份名称(如"Banten"),无法匹配城市数据的键名。
  2. 城市数据遍历逻辑错误:ListOfCity是数组结构,每个元素是单个key的对象(如{banten: [...]}),直接遍历数组取option.kota会返回undefined,因为对象中没有kota属性。
  3. 未实现城市列表动态过滤:城市下拉框未关联选中的省份,始终遍历所有城市数据,无法展示对应省份的城市。
  4. 事件绑定不合理:用onClick触发数据请求会导致点击下拉框就执行,而非选中选项后执行,应该在onChange中触发。

分步修复方案

1. 修正省份下拉框的value绑定

修改省份选项渲染逻辑,将value设置为省份对应的key:

{ListOfProvinsi.map((option, index) => (
  <option key={index} value={option.value}>{option.provinsi}</option>
))}

2. 优化城市数据结构(提升查询效率)

将ListOfCity从数组改为对象,方便通过省份key直接获取城市列表:

const CityMap = {
  jatim: [
    { kota: "Bangkalan" },
    { kota: "Banyuwangi" },
    // 保留原所有城市数据
  ],
  jabar: [
    { kota: "Kabupaten Bandung" },
    { kota: "Kabupaten Bandung Barat" },
    // 保留原所有城市数据
  ],
  jateng: [/* 原城市数据 */],
  yogya: [/* 原城市数据 */],
  dki: [/* 原城市数据 */],
  banten: [/* 原城市数据 */],
};

若不想修改原结构,可通过数组查找替代:ListOfCity.find(item => Object.keys(item)[0] === selected)?.[selected]

3. 动态渲染对应省份的城市列表

修改城市下拉框,根据选中的省份key展示对应城市,并添加默认提示选项:

<select
  value={selected2}
  onChange={(e) => {
    setSelected2(e.target.value);
    handleKota();
  }}
  disabled={!selected} // 未选省份时禁用
  className="form-select appearance-none block w-72 px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding bg-no-repeat border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none"
>
  <option value="">选择城市</option>
  {selected && CityMap[selected]?.map((city, index) => (
    <option key={index} value={city.kota}>{city.kota}</option>
  ))}
</select>

4. 修正事件触发逻辑

省份下拉框在onChange中触发数据请求,同时重置选中的城市:

<select
  value={selected}
  onChange={(e) => {
    setSelected(e.target.value);
    setSelected2(""); // 切换省份清空城市选择
    handleProvinsi();
  }}
  className="form-select appearance-none block w-72 px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding bg-no-repeat border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none"
>
  <option value="">选择省份</option>
  {ListOfProvinsi.map((option, index) => (
    <option key={index} value={option.value}>{option.provinsi}</option>
  ))}
</select>

5. 优化数据请求与表格展示

调整请求函数,移除不必要的事件参数,并优化表格数据展示逻辑,根据是否选中城市切换展示省份/城市数据:

const handleProvinsi = async () => {
  try {
    setIsLoading(true);
    const result = await getCountPoiCategoryProvinsi(selected);
    setDataProvinsi(result);
  } catch (error) {
    console.error("获取省份数据失败:", error);
  } finally {
    setIsLoading(false);
  }
};

const handleKota = async () => {
  try {
    setIsLoading(true);
    const result = await getCountPoiCategoryKota(selected, selected2);
    setDataKota(result);
    setDataProvinsi([]); // 选中城市后清空省份数据
  } catch (error) {
    console.error("获取城市数据失败:", error);
  } finally {
    setIsLoading(false);
  }
};

表格部分优化:

<tbody>
  {isLoading && <tr><td colSpan="3" className="py-4 text-center">loading...</td></tr>}
  {!isLoading && !selected2 ? (
    dataProvinsi.length === 0 ? (
      <tr><td colSpan="3" className="py-4 text-center">Data Tidak Ditemukan</td></tr>
    ) : (
      dataProvinsi.map((item) => (
        <tr key={`${item.provinsi}-${item.category}`} className="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
          <td className="py-4 px-7 font-medium text-[#696974] whitespace-nowrap dark:text-white">{item.provinsi}</td>
          <td className="py-4 px-7 font-medium text-[#696974] whitespace-nowrap dark:text-white">{item.category}</td>
          <td className="py-4 px-7 font-medium whitespace-nowrap dark:text-white">
            {item.jumlah_category.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".")}
          </td>
        </tr>
      ))
    )
  ) : (
    dataKota.length === 0 ? (
      <tr><td colSpan="3" className="py-4 text-center">Data Tidak Ditemukan</td></tr>
    ) : (
      dataKota.map((item) => (
        <tr key={`${item.kota}-${item.category}`} className="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
          <td className="py-4 px-7 font-medium text-[#696974] whitespace-nowrap dark:text-white">{item.kota}</td>
          <td className="py-4 px-7 font-medium text-[#696974] whitespace-nowrap dark:text-white">{item.category}</td>
          <td className="py-4 px-7 font-medium whitespace-nowrap dark:text-white">
            {item.jumlah_category.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".")}
          </td>
        </tr>
      ))
    )
  )}
</tbody>

内容的提问来源于stack exchange,提问作者Arbi Dwi Wijaya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:46:59