React18中react-leaflet重复渲染致多地理编码器问题求助
React18升级后react-leaflet自定义Geocoder出现两个的原因及解决办法
这个问题核心出在React18的Strict Mode默认行为上,和useMap钩子本身关系不大,是渲染流程变化导致的副作用重复执行:
- React17的Strict Mode只会在挂载前做一次检查,不会触发组件的「卸载-重新挂载」流程;但React18在开发环境下,Strict Mode会对组件进行挂载→卸载→重新挂载的双重渲染,目的是检测未清理的副作用。
- 如果你的Geocoder组件是直接在组件顶层(没包裹在
useEffect里)执行map.addControl这类操作,双重渲染会导致控件被添加两次,自然出现两个地理编码器。 - 你在React DevTools看到
useMap的变化,本质是组件被重新挂载了一次,第二次挂载时又获取了map实例并重复添加了控件。
解决办法
把控件的添加/移除逻辑放到useEffect里,并添加清理函数确保卸载时移除控件:
import { useMap } from 'react-leaflet'; import L from 'leaflet'; // 确保引入leaflet-geocoder的样式和脚本 import 'leaflet-geocoder/dist/Control.Geocoder.css'; import 'leaflet-geocoder/dist/Control.Geocoder.js'; function Geocoder() { const map = useMap(); useEffect(() => { // 初始化并添加地理编码器控件 const geocoderControl = L.Control.Geocoder({ position: 'topright', // 你的其他配置项 }).addTo(map); // 清理函数:组件卸载时移除控件 return () => { map.removeControl(geocoderControl); }; }, [map]); // 依赖map实例,确保只在map可用时执行一次 // 自定义Leaflet控件不需要渲染React元素,返回null即可 return null; }
这样即使React18触发双重渲染,第一次挂载添加的控件会在卸载时被移除,第二次挂载重新添加,最终只会保留一个控件。另外注意生产环境下Strict Mode不会触发双重渲染,修复后开发和生产环境都会正常。
内容的提问来源于stack exchange,提问作者user17145524
相关产品推荐
相关产品推荐

