React+react-leaflet地图页面无法加载,控制台报key缺失、对象不可作为React子元素错误
问题定位
- 警告
Each child in a list should have a unique "key" prop:使用map遍历渲染GeoJSON组件时未添加唯一key属性,React需要该属性完成虚拟DOM比对。 - 报错
Objects are not valid as a React child:核心错误是混淆了filter和map的用法。filter的回调需要返回布尔值来筛选数组元素,但你在searchCity的filter回调中直接返回了city对象或者React组件,导致最终返回的数组中存在未被处理的原始GeoJSON对象,直接渲染这类对象就会触发报错。 - 你猜测的
preventDefault问题不成立:input的onChange事件没有需要阻止的默认行为,该段代码不会影响页面加载。 - 额外逻辑缺陷:同时渲染全量城市图层
demarcatedCountry()和搜索结果searchCity(),会导致图层重复加载。
解决方案
- 拆分搜索逻辑:先通过
filter筛选出匹配的城市,再通过map将筛选结果转换为GeoJSON组件 - 为所有遍历生成的
GeoJSON组件添加唯一key属性,使用城市名称作为唯一标识即可 - 调整渲染逻辑:存在搜索词时渲染筛选后的结果,否则渲染全量城市图层
- 删除
onChange中冗余的preventDefault代码
修改后完整代码
import React,{useState} from 'react'; import { MapContainer,TileLayer,GeoJSON } from 'react-leaflet'; import "leaflet/dist/leaflet.css"; import Cities from './cities.json'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSearch } from '@fortawesome/free-solid-svg-icons' import './CountryMap.css' const CountryMap = () => { const [searchtext, setsearch] = useState(''); const demarcatedCountry = () => { return Cities.features.map((City) => ( <GeoJSON key={City.properties.NAME_3} data={City} /> )); } const searchCity = () => { // 先筛选匹配的城市 const matchedCities = Cities.features.filter(city => { return searchtext === "" || searchtext === city.properties.NAME_3 }) // 再转换为GeoJSON组件 return matchedCities.map(city => ( <GeoJSON key={city.properties.NAME_3} data={city} style={{ color:"red", fillColor:"pink" }} /> )) } return ( <div> <form action="" className='form'> <input value={searchtext} type="text" placeholder="Search city" className="searchBar" onChange={e => setsearch(e.target.value)} /> <FontAwesomeIcon icon={faSearch} className="searchIcon" /> </form> <MapContainer center={[30.964750, 70.939934]} zoom={5} style={{ width:"100%", height:"100vh" }} > <TileLayer attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> {/* 有搜索词渲染搜索结果,否则渲染全量图层 */} {searchtext ? searchCity() : demarcatedCountry()} </MapContainer> </div> ); }; export default CountryMap;
内容的提问来源于stack exchange,提问作者Ahmad Noor khan
相关产品推荐
相关产品推荐

