React Native Maps 点击Marker时Callout错位、Marker显示异常
触发该异常的核心原因
这类错位弹窗、样式临时串换的问题,是当前react-native-maps@0.27.1版本的组件复用机制和代码写法共同触发的,具体有三个核心问题:
- 渲染Marker列表时使用数组下标作为
key,没有使用点位的唯一标识。当地图组件为了性能复用Marker实例时,会直接绑定错位的数据源,出现点击位置A弹出位置B的Callout、Marker颜色临时串换的现象。 - 给Marker设置了
tracksViewChanges={true},这个属性在该版本的原生实现里,会让Marker实例持续监听内部视图变更,和组件复用逻辑存在冲突,进一步放大数据绑定错位的问题;等用户关闭异常Callout时,组件会重新拉取正确的绑定数据,才会恢复正常显示。 - 渲染Callout内部的监测值列表时,同样使用遍历的数组下标作为
key,会导致Callout内部的内容在组件复用时出现错位。
针对性修复方案
按以下三处调整即可稳定解决问题:
- 替换所有动态列表的
key为唯一稳定值,禁止使用数组下标作为key- Marker的
key直接使用station.id这类唯一标识 - Callout内部渲染监测项的
key,使用监测项的字段名作为key
- Marker的
- 将Marker的
tracksViewChanges设置为false,减少不必要的视图重绘,规避该版本的已知冲突 - 数据加载阶段就提前整理好固定的经纬度对象,不要在每次渲染Marker时临时创建coordinate对象,减少重复对象创建带来的复用异常
调整后的核心代码示例
// 接口返回数据阶段提前整理固定字段 data = data.map((value) => { value.name = value.device; value.show = true; value.color = function_that_determines_color(value.record); // 提前存储固定的坐标对象,避免渲染时重复创建 value.coordinate = { latitude: value.latitude, longitude: value.longitude }; return value; }); // Marker渲染部分修改后 { stations_info.filter(v => v.show).map((station) => ( <Marker coordinate={station.coordinate} title={station.name} pinColor={station.color} tracksViewChanges={false} // 使用唯一id作为key,不使用数组下标 key={station.id} > <Callout onPress={() => navigation.navigate('Info', { station_id: station.id, name: station.name })}> <Text>Station: {station.name}</Text> { Object.entries(station.record).map((value) => ( // 使用字段名作为key,不使用遍历下标 <Text key={value[0]}>{value[0]}: {value[1]}</Text> )) } <Text>Click to see more</Text> </Callout> </Marker> )) }
兜底方案
如果调整上述代码后仍偶现错位,可通过给每个Marker绑定单独的ref,在用户点击Marker时手动调用markerRef.showCallout(),关闭弹窗时调用dismissCallout(),绕开版本内置的自动绑定逻辑即可。
内容的提问来源于stack exchange,提问作者Allen
相关产品推荐
相关产品推荐

