How to dynamically update the MapMarker image collection based on whether or not selected?

I was recently puzzled by this, and I want to dynamically update map marker images based on whether the map marker is selected / active or not (each MapMarker has a category that refers to either the active image or the default image from two image collections: interest and IconsSelected interest.In essence, I have a collection of MapMarkers that are displayed with display through a collection of map markers.Each MapMarker is a child component of MapView.Marker.

I would like to display all MapMarkers in the unselected / inactive default state, having a default image from objects of interest, when it is selected that the MapMarker image should be changed to the active image from the list of interestsIconsSelected, when another MapMarker selected the previous one should return to the default image , and the new one should change to the selected image.

Currently, I can display map markers with a default image, but when choosing mapmarker the image does not seem to change immediately if you do not want to zoom in / out again, i.e. -render, I would like so that clicking on MapMarker immediately caused the image to refresh.

MapScreen.js: Displays MapView for all MapView.Marker MapMarkers through the map.

<MapView ref={map => { this._map = map }} style={Styles.Map.map} initialRegion={this.props.region} onRegionChange={this.handleRegionChange} > { this.props.events .filter(this.eventFilterTimeNearFuture) .filter(this.eventFilterTimeNotPast) .filter(this.eventFilterDistance) .filter(this.eventFilterInterest) .map(e => <MapView.Marker key={e.id} onPress={() => this.handleLocationPush(e)} // Set selected event state coordinate={e.location} > <MapMarker event={e} size={this.state.markerSize} selected={this.state.selectedEvent} // The selected event set by state call. /> </MapView.Marker> ) } { !this.props.regionMock && <MapView.Marker key={'userLocation'} coordinate={this.props.region} > <MapMarker size={'user'} /> </MapView.Marker> } </MapView> 

MapMarker.js

 import {interestIcons, interestColors, interestIconsSelected} from "../../utils/Icons"; import {Styles} from '../../StyleProvider'; class MapMarker extends React.Component { constructor() { super(); this.state = { initialized: false, active: false, }; }; componentWillReceiveProps(nextProps) { if (!this.state.initialized) { console.log('initialization'); this.setState({initialized: true}); } else { // If the nextProps.selected prop exists which it will if (nextProps.selected) { // If the nextProps.selected props id equals the this event id then selected else non-selected. if (nextProps.selected.id === nextProps.event.id) { console.log('SELECTED: ' + JSON.stringify(nextProps.selected)); // set staae to active this.setState({ active: true }); console.log(interestIconsSelected[nextProps.event.interest[0]]); } else { // set state to not active // console.log('NON-SELECTED: ' + JSON.stringify(nextProps.event)); this.setState({ active: false }); } this.forceUpdate(); } } } markerIcon(interest) { return this.state.active ? interestIconsSelected[interest] : interestIcons[interest]; } renderIcon() { if (this.props.event.type === 'Event') { return ( <Image source={this.markerIcon(this.props.event.interest[0])} style={Styles.MapMarker.eventImage} /> ) } } 

The WillReceiveProps (nextProps) component still works, and this points to the "fairly good" current selected event and all unselected events.

I tried to set the image source using say this.state.image and then setting the state of the image in the this.state.image component accordingly, i.e.

 if (nextProps.selected) { // If the nextProps.selected props id equals the this event id then selected else non-selected. if (nextProps.selected.id === nextProps.event.id) { console.log('SELECTED: ' + JSON.stringify(nextProps.selected)); // set staae to active this.setState({ active: true, image: this.markerIcon(nextProps.event.interest[0], true) }); console.log(interestIconsSelected[nextProps.event.interest[0]]); } else { // set state to not active console.log('NON-SELECTED: ' + JSON.stringify(nextProps.event)); this.setState({ active: false, image: this.markerIcon(nextProps.event.interest[0], false) }); } } renderIcon() { if (this.props.event.type === 'Event') { return ( <Image source={this.state.image} style={Styles.MapMarker.eventImage} /> ) } } 

Changing the state of the image seems to work more efficiently, as the image will immediately change, but then it seems that the image on the original render will not be set at all, so it will be a blank icon until it is selected.

Thanks a lot, appreciate any help.

Update: Trying to define an image component in MapView.Marker and this will not work.

 this.state.markers .map(e => <MapView.Marker key={e.id} onPress={() => this.handleLocationPush(e)} coordinate={e.location} > {/* <MapMarker event={e} size={this.state.markerSize} /> */} <Image source={this.state.selectedEvent === e ? interestIconsSelected[e.interest[0]] : interestIcons[e.interest[0]]} style={Styles.MapMarker.eventImage} /> </MapView.Marker> ) 

BUT this works, although you seem to be unable to apply style to MapView.Marker, but this is not an implementation, I would like for me to save the custom MapMarker component

 this.state.markers .map(e => <MapView.Marker key={e.id} onPress={() => this.handleLocationPush(e)} coordinate={e.location} image={this.state.selectedEvent === e ? interestIconsSelected[e.interest[0]] : interestIcons[e.interest[0]]} /> ) 

The above two snipers of the code, either using the image, refer directly to MapView.Marker, or have the image component directly in MapView.Marker are not suitable, as using the child component MapMaper.

+7
reactjs react-native airbnb react-native-maps
source share
1 answer

you use the componentWillReceiveProps lifecycle method that did not execute on the first render, you also use this.state.initialized with false in the constructor state, so you need to double-click to make it active

 componentWillReceiveProps(nextProps) { // it did not run at first render if (!this.state.initialized) { // this.state.initialized with is false in constructor console.log('initialization'); this.setState({initialized: true}); } ....... } 

you can completely remove your componentWillReceiveProps if you do something like this

 markerIcon() { //did not get interest directly instead access it from props return this.props.selected.id === this.props.event.id ? interestIconsSelected[this.props.event.interest[0]] : interestIcons[this.props.event.interest[0]]; } 

here you compare two objects with the same comparison, since they are deep, you can use something like this instead of not confusing Babel in more detail

 <Image // use this.state.selectedEvent.id === e.id instead of this.state.selectedEvent === e source={this.state.selectedEvent.id === e.id ? interestIconsSelected[e.interest[0]] : interestIcons[e.interest[0]]} style={Styles.MapMarker.eventImage} /> 

I hope this helps. Thanks.

+1
source share

All Articles