在 react-admin 的选项卡形式内使用自定义地图组件呈现问题
Rendering issue with custom map component inside tabbed form of react-admin
我在一个项目中使用 React-admin 来获取一些资源,我使用选项卡式表单来更好地组织字段和输入。我基于 react-leaflet 创建了一个相当简单的自定义地图组件,我在这些选项卡式表单中使用了它。
我遇到了一个奇怪的问题,即当地图位于第一个选项卡以外的其他选项卡上时,其内容无法正确显示。似乎地图“认为”视口比实际小得多。重新加载页面(甚至只是在 Chrome 中打开开发人员工具)会强制重新呈现页面并导致地图开始正常运行。
为了更好地演示,我创建了这个简单的 Codesandbox project。它有来自 RA 教程的用户资源,带有两个选项卡。两者都包含地图组件的一个实例,但第一个选项卡上的地图可以立即正常工作,而第二个选项卡上的地图则呈现不正确。
我承认我在这些事情上仍然有点菜鸟,所以我很可能做错了什么,但我已经为此挠头好几个小时了,我想开始消除可能的罪魁祸首。
欢迎任何见解。
非常感谢您的宝贵时间。
这个问题已经在SO中讨论了很多。如果您稍微搜索一下,就会找到原因。您实际需要做的是两件事:
- 在切换选项卡时将
setInterval
与地图的invalidateSize
方法结合使用,然后在组件卸载时将其清除
- 使用
useEffect
更改地图缩放和视图,因为它们是不可变的。
因此,由于您使用的是 react-leaflet 版本 2。7.x 您需要使用 ref:
获取地图实例
const mapRef = useRef();
useEffect(() => {
if (!mapRef.current) return;
const map = mapRef.current.leafletElement;
const mapZoom = zoom || defaultZoom;
let intervalInstance;
if (!center && marker) {
map.setView(marker, mapZoom);
intervalInstance = setInterval(() => map.invalidateSize(), 100);
} else if (!center) {
map.setView([0.0, 0.0], mapZoom);
}
map.setZoom(mapZoom);
return () => clearInterval(intervalInstance);
}, []);
<LeafletMap
ref={mapRef}
center={marker}
zoom={defaultZoom}
className={classes.leafletContainer}
>
我在一个项目中使用 React-admin 来获取一些资源,我使用选项卡式表单来更好地组织字段和输入。我基于 react-leaflet 创建了一个相当简单的自定义地图组件,我在这些选项卡式表单中使用了它。
我遇到了一个奇怪的问题,即当地图位于第一个选项卡以外的其他选项卡上时,其内容无法正确显示。似乎地图“认为”视口比实际小得多。重新加载页面(甚至只是在 Chrome 中打开开发人员工具)会强制重新呈现页面并导致地图开始正常运行。
为了更好地演示,我创建了这个简单的 Codesandbox project。它有来自 RA 教程的用户资源,带有两个选项卡。两者都包含地图组件的一个实例,但第一个选项卡上的地图可以立即正常工作,而第二个选项卡上的地图则呈现不正确。
我承认我在这些事情上仍然有点菜鸟,所以我很可能做错了什么,但我已经为此挠头好几个小时了,我想开始消除可能的罪魁祸首。
欢迎任何见解。
非常感谢您的宝贵时间。
这个问题已经在SO中讨论了很多。如果您稍微搜索一下,就会找到原因。您实际需要做的是两件事:
- 在切换选项卡时将
setInterval
与地图的invalidateSize
方法结合使用,然后在组件卸载时将其清除 - 使用
useEffect
更改地图缩放和视图,因为它们是不可变的。
因此,由于您使用的是 react-leaflet 版本 2。7.x 您需要使用 ref:
获取地图实例const mapRef = useRef();
useEffect(() => {
if (!mapRef.current) return;
const map = mapRef.current.leafletElement;
const mapZoom = zoom || defaultZoom;
let intervalInstance;
if (!center && marker) {
map.setView(marker, mapZoom);
intervalInstance = setInterval(() => map.invalidateSize(), 100);
} else if (!center) {
map.setView([0.0, 0.0], mapZoom);
}
map.setZoom(mapZoom);
return () => clearInterval(intervalInstance);
}, []);
<LeafletMap
ref={mapRef}
center={marker}
zoom={defaultZoom}
className={classes.leafletContainer}
>