React Native中如何通过函数调用触发Fast Refresh更新MapboxGL MarkerView
React Native 触发MapboxGL MarkerView刷新的解决方案
问题根源分析
你的代码里存在几个关键问题导致Marker无法正常刷新:
- 按钮点击逻辑错误:当前按钮调用
renderLoc()仅返回组件,没有触发数据更新流程 - setState异步特性导致数据错误:
getNewPins中调用setBoundingBox后直接使用boundingBox,此时拿到的是旧值,无法获取新区域内的位置 - Marker的Key不唯一:使用
data.coordinates[0]作为key,若多个Marker经度相同,React会复用旧组件,不重新渲染位置 - MapboxGL MarkerView的缓存特性:部分场景下即使state更新,Marker可能因内部缓存不刷新
具体修改步骤
1. 修正按钮点击事件
把按钮的onPress改为调用获取新数据的getNewPins(),而不是无意义的renderLoc():
<TouchableOpacity style={styles.searchAreaBtn} onPress={getNewPins}> <NooksText style={styles.searchAreaBtnText}>Search This Area</NooksText> </TouchableOpacity>
2. 修复setState异步问题
在getNewPins中,直接使用计算后的新boundingBox值,不要依赖刚更新的state:
const getNewPins = async () => { const box = await getBoundingBox(); // 直接计算新的boundingBox并保存到变量 const newBoundingBox = { north: box[0][1] + 0.15, east: box[0][0] + 0.15, south: box[1][1] + 0.15, west: box[1][0] + 0.15, }; setBoundingBox(newBoundingBox); // 使用newBoundingBox而非state中的旧值 const { locations } = await getLocations(newBoundingBox); // ...后续逻辑保持不变 };
3. 确保Marker的Key唯一
将Marker的key改为使用唯一标识(比如每个location的lid),避免React复用组件:
// 先在retObj中加入lid字段 const retObj = lids.map((lid: number) => { const post = groupedPosts[lid]; const location = locations.find((loc: any) => loc.lid === lid); return { lid: lid, // 新增唯一标识 locationName: location.display_name, coordinates: [Number(location.longitude), Number(location.latitude)], posts: post, }; }); // 然后将Marker的key改为data.lid <MapboxGL.MarkerView key={data.lid} id={data.locationName} coordinate={data.coordinates} >
4. 强制触发Marker重渲染(可选)
如果上述修改后仍不生效,可以给包裹Marker的View添加动态key,强制React重新渲染所有Marker:
<View key={`markers-${pinData.length}-${Date.now()}`}> {pinData.map((data) => ( <MapboxGL.MarkerView key={data.lid} id={data.locationName} coordinate={data.coordinates} > {/* ...Marker内容 */} </MapboxGL.MarkerView> ))} </View>
内容的提问来源于stack exchange,提问作者Kevin Su
相关产品推荐
相关产品推荐

