React省市级联下拉框无数据显示问题求助
省市级联下拉框无内容问题修复
问题核心原因
你的代码存在4个关键问题导致城市下拉框无内容:
- 省份下拉框未绑定正确value:渲染省份选项时只设置了显示文本,未将
value绑定为对应省份的key(如banten),导致selected存储的是省份名称(如"Banten"),无法匹配城市数据的键名。 - 城市数据遍历逻辑错误:
ListOfCity是数组结构,每个元素是单个key的对象(如{banten: [...]}),直接遍历数组取option.kota会返回undefined,因为对象中没有kota属性。 - 未实现城市列表动态过滤:城市下拉框未关联选中的省份,始终遍历所有城市数据,无法展示对应省份的城市。
- 事件绑定不合理:用
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
相关产品推荐
相关产品推荐

