React Native中使用map函数渲染MapView Marker时遇undefined问题
Hey there, let's break down why you're seeing that undefined error when trying to render your markers, and fix it step by step. I noticed a few critical issues in your code that are causing this problem:
Key Issues in Your Code
Your
mapfunction doesn't return values
In yourcomponentDidMountwhen updating markers viasetState, themapcallback only modifies matching markers but doesn't return anything. This means the resulting array will be filled withundefinedvalues, which causes errors when you try to accessmarker.latitudein the render method.Incorrect watch ID retrieval
ThewatchIdisn't part ofposition.coords— it's the return value ofnavigator.geolocation.watchPosition()itself. Your current code is trying to get it from the wrong place, soidbecomesNaN, and your code can never match existing markers.Direct state access in async
setStatesetStateis asynchronous, so usingthis.state.markersdirectly inside it can lead to using stale state. You should use the functional update pattern to ensure you're working with the latest state.
Fixed Code
Here's the corrected version of your component with explanations of the changes:
import React, {Component} from 'react'; import {AppRegistry, Text, View, StyleSheet} from 'react-native' import MapView from 'react-native-maps' export default class myapp extends Component{ constructor(props){ super(props); this.state ={ markers: [ { watchId: 0, latitude:3, longitude:2 }, { watchId: 2, latitude:3, longitude:2 } ], watchId: null // Store watchId to clean up later if needed } } componentDidMount(){ // Get the correct watchId from the watchPosition return value const watchId = navigator.geolocation.watchPosition((position)=>{ const lat = parseFloat(position.coords.latitude) const long = parseFloat(position.coords.longitude) // Use functional setState to access latest state this.setState(prevState => { let found = false; // Map returns updated markers or original ones const updatedMarkers = prevState.markers.map(marker =>{ if(marker.watchId === watchId){ found = true; // Return a new object instead of mutating the old one (immutable update) return {...marker, latitude: lat, longitude: long}; } // Return unmodified marker to keep it in the array return marker; }); if(!found){ // Add new marker without replacing the entire array return { markers: [...updatedMarkers, {watchId: watchId, latitude: lat, longitude: long}] }; } return { markers: updatedMarkers }; }); }, null, {timeout:0, distanceFilter:0}); // Save watchId to state for potential cleanup (like in componentWillUnmount) this.setState({ watchId }); } // Optional: Clean up geolocation watch when component unmounts componentWillUnmount() { if(this.state.watchId){ navigator.geolocation.clearWatch(this.state.watchId); } } render(){ return( <View> <MapView style={{height:350,width:350,marginTop:300,alignSelf:'center'}} initialRegion={{ latitude: 37.33, longitude: -121.4024, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }} showsUserLocation={true} followsUserLocation={true} showsMyLocationButton={true} > {/* Add unique key prop to avoid React warnings */} {this.state.markers.map(marker =>{ return( <MapView.Marker key={marker.watchId} coordinate={{latitude:marker.latitude,longitude:marker.longitude}} title={"title"} description={"description ey"} /> ); })} </MapView> </View> ); } } AppRegistry.registerComponent('myapp',()=>myapp);
Additional Notes
- Immutable Updates: Instead of mutating the original marker object, we return a new object with the updated coordinates. This helps React detect changes properly.
- Key Prop: Adding a
keyprop to eachMapView.Markerprevents React from throwing list rendering warnings and improves performance. - Cleanup: The
componentWillUnmountmethod clears the geolocation watch to prevent memory leaks when the component is removed.
内容的提问来源于stack exchange,提问作者Parth Patel

