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>
)