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

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(),会导致图层重复加载。

解决方案

  1. 拆分搜索逻辑:先通过filter筛选出匹配的城市,再通过map将筛选结果转换为GeoJSON组件
  2. 为所有遍历生成的GeoJSON组件添加唯一key属性,使用城市名称作为唯一标识即可
  3. 调整渲染逻辑:存在搜索词时渲染筛选后的结果,否则渲染全量城市图层
  4. 删除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='&copy; <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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:54:04