Home > Net >  React Native Expo MapView - Passing Marker Details to an Expanding Bottom View
React Native Expo MapView - Passing Marker Details to an Expanding Bottom View

Time:10-14

I'm building an app with React Native Expo which has a screen of various markers. These come from a firebase JSON file. Everything works fine except for the view at the bottom of the screen, which I want to display information on the marker point when clicked (Title, Description, Attached images etc.).

I've tried multiple ways, in this example using the map method, however this displays all markers at once in the bottom view. I want to display the currently selected marker only. This bottom view also has a function to minimize / expand which is irrelevant.

I've added an onPress event which I would like it to set the current displayed marker to the marker pressed.

Here is what I have done:

// ## Imports
// ## Firebase codeblock

function MapExp() {

   // I've removed irrelevant constants/functions for minimizing bottom view.
   
   // Initial empty array of users (marker points)
   const [users, setUsers] = useState([]); 
   const windowHeight = Dimensions.get("window").height;

   const [point, setPoint] = useState([]);

   const pressMarker = (i) => {
      console.log(i.Title);
      console.log(i.Description);
      setPoint(i.Title);
    };

   useEffect(() => {
      const dbh = firebase.firestore();
      dbh
      .collection("Map_DB")
      .get()
      .then((querySnapshot) => {
         const users = [];
         querySnapshot.forEach((documentSnapshot) => {
            users.push({
               ...documentSnapshot.data(),
               key: documentSnapshot.id,
            });
         });
         // Filling array 'users' with all the map markers from DB
         setUsers(users);
      });
   }, []);

   
   return (
      <MapView
        initialRegion={{ latitude: 48.87389506, longitude: 2.295039178, latitudeDelta: 0.01, longitudeDelta: 0.01 }}
        r
        style={{ flex: 1, minHeight: windowHeight }}
        provider={PROVIDER_GOOGLE}
        customMapStyle={mapStyle}
        showsUserLocation={true}
      >
       {users.map((i, index) => (
          <Marker
            key={index}
            onPress = {() => pressMarker(i)}
            coordinate={{
              latitude: i.Latitude,
              longitude: i.Longitude,
            }}
            title={i.Title}
            description={i.Description}
          />
        ))}
      </MapView>

      {/* ##### ATTEMPTING TO ADD EXPAND VIEW ###### */}
      {users.map((i, index) => (
         <View style={styles.expandingView}>
            <TouchableOpacity style={styles.touchableButton } onPress={toggleCollapsed}>
               <Image source={require("../assets/upArrowWhite.png")} style={styles.arrowLogo}></Image>
            </TouchableOpacity>
            <Animated.View style={{maxHeight: animationHeight}}>
               <View style={styles.pointImageContainer}>
                  <Image style={styles.pointImage} source={require("../assets/sunsetCrop.png")}  />
               </View>
               <View style={styles.paragraphContainer}>
                  <Text style={styles.paragraph}>{i.Title}</Text>
                  <Text style={styles.paragraph}>{i.Description}</Text>
               </View>
            </Animated.View>
         </View>
      ))}
  );
}
I have also added the console log statements to see if I can correctly log the currently pressed marker's details 

export default MapExp;

The pressMarker is supposed to trigger the setPoint but im unsure how to do this. I would then want the bottom view "expand view" to display the Title etc as text.

Is there a better way to pass this current marker data into the expand view / text components of the screen?

In the pressMarker event I also succesfully can log in the console the pressed markers Title and Description with no issues:

pressMarker = (i) => {
      console.log(i.Title);
      console.log(i.Description);
      setPoint(i.Title);

The issue is setting the current "Point" to the selected marker to be displayed on the expanding view at the bottom of the screen.

CodePudding user response:

First, you need to create a component to show extra details of a marker. it can be a separated component or define implicitly.

For toggling between showing/hiding the Details component, you need to add a showDetails: false property for each object in the users array.

also don't forget to use an id for each element

The sample data will look like this:

const users = [
  {id: 0, title: 'first point', description: '', coordinatets: {lat: 0, long: 0}, showDetails: false},
  // rest of the data...
]

As you see below, I wrap the Marker and Details with a TouchableOpacity element which can be changed to your desire.

function MarkerWithDetails({point, onToggle}) {
  const {coordinates, title, description, showDetails} = point;

  return(
    <TouchableOpacity onPress={onToggle}>
      <Marker coordinate={{latitude: lat, longitude: long}}/>
      {showDetails && <Details title={title} description={description}/>}
    </TouchableOpacity>
  )
}

Now, the Details component only renders the extra details if it's has a showDetails: true property.

It's time to render MarkerWithDetails, also you need a handler function to toggles between hiding and showing Details by changing the showDetails value between false and true:

handleToggle = (id) => {
  setUsers(prevState => prevState.map(user => (  
        user.id === id ? {...user, showDetails: !user.showDetails} : user     
     ))
  )
}

return (
    <MapView
        initialRegion={{ latitude: 48.87389506, longitude: 2.295039178, latitudeDelta: 0.01, longitudeDelta: 0.01 }}
        r
        style={{ flex: 1, minHeight: windowHeight }}
        provider={PROVIDER_GOOGLE}
        customMapStyle={mapStyle}
        showsUserLocation={true}
      >
       {users.map((user) => (<MarkerWithDetials point={user} onToggle={() => handleToggle(user.id)}/>))}
    </MapView>
)
  • Related