【发布时间】:2021-11-21 02:22:38
【问题描述】:
我正在开发一个地图应用程序,它使用 JSON 文件来绘制标记并在地标上呈现信息。目前我已经实现了 React Native Carousel 功能,当按下标记时它也会捕捉到地标项目。它还将 Carousel 项捕捉到当前选定的标记。不过我也希望实现一个底部工作表,它可以向上滚动并呈现额外信息:地标名称和描述。
使用与渲染轮播数据相同的方法:名称和图像,尝试在底部屏幕中渲染当前地标时出现错误。
错误信息:
TypeError: undefined is not an object (evalating '_ref2.item')
在我的代码中,renderInner 是一个函数,它应该呈现带有描述的底页,同时还调用 renderHeader 函数——它应该呈现底页的标题以包含地标的标题——“名称”。
这是我当前的代码:
import React, { Component } from "react";
import { StyleSheet,View, Text, Image, Dimensions } from "react-native";
import MapView, {PROVIDER_GOOGLE, Marker, Callout } from "react-native-maps";
import Carousel from "react-native-snap-carousel";
import { LinearGradient } from "expo-linear-gradient";
import BottomSheet from 'reanimated-bottom-sheet';
import Animated from 'react-native-reanimated';
const { block, set, greaterThan, lessThan, Value, cond, sub } = Animated
const windowHeight = Dimensions.get("window").height;
export default class ParisMap extends Component {
// BottomScreen Constants
trans = new Value(0)
untraversedPos = new Value(0)
prevTrans = new Value(0)
headerPos = block([
cond(
lessThan(this.untraversedPos, sub(this.trans, 100)),
set(this.untraversedPos, sub(this.trans, 100))
),
cond(
greaterThan(this.untraversedPos, this.trans),
set(this.untraversedPos, this.trans)
),
set(this.prevTrans, this.trans),
this.untraversedPos,
])
static navigationOptions = {
title: "Map",
};
state = {
markers: [],
coordinates: [
{
name: "Louvre Museum",
latitude: 48.86074344,
longitude: 2.337659481,
Description: "Former historic palace housing huge art collection, from Roman sculptures to da Vinci's 'Mona Lisa.'",
image: require("../assets/louvre.jpeg"),
},
{
name: "Arc de Triomphe",
latitude: 48.87389506,
longitude: 2.295039178,
Description: "Iconic triumphal arch built to commemorate Napoleon's victories, with an observation deck.",
image: require("../assets/louvre.jpeg"),
},
{
name: "Eiffel Tower",
latitude: 48.85841765,
longitude: 2.294465185,
Description: "Gustave Eiffel's iconic, wrought-iron 1889 tower, with steps and elevators to observation decks.",
image: require("../assets/louvre.jpeg"),
},
{
name: "Cathédrale Notre-Dame",
latitude: 48.85294707,
longitude: 2.350142233,
Description: "Towering, 13th-century cathedral with flying buttresses & gargoyles, setting for Hugo's novel.",
image: require("../assets/louvre.jpeg"),
},
{
name: "Sacré-Cœur",
latitude: 48.88670304,
longitude: 2.343082828,
Description: "Iconic, domed white church, completed in 1914, with interior mosaics, stained-glass windows & crypt.",
image: require("../assets/louvre.jpeg"),
},
],
};
onCarouselItemChange = (index) => {
let location = this.state.coordinates[index];
this._map.animateToRegion({
latitude: location.latitude,
longitude: location.longitude,
latitudeDelta: 0.0045,
longitudeDelta: 0.0045,
});
this.state.markers[index].showCallout();
};
onMarkerPressed = (location, index) => {
this._map.animateToRegion({
latitude: location.latitude,
longitude: location.longitude,
latitudeDelta: 0.0045,
longitudeDelta: 0.0045,
});
this._carousel.snapToItem(index);
this._bottomsheet.snapToItem(index);
};
renderCarouselItem = ({ item }) => (
<View style={styles.cardContainer}>
<Text style={styles.cardTitle}>{item.name}</Text>
<Image style={styles.cardImage} source={item.image} />
</View>
);
renderInner = ({ item }) => (
<View style={styles.bottomSheetInnerContainer}>
<Animated.View
style={{
zIndex: 1,
transform: [
{
translateY: this.headerPos,
},
],
}}
>
{this.renderHeader({ item })}
</Animated.View>
{/* <Text style={styles.descriptionText}> Here is some sample text</Text> */}
<Text style={styles.descriptionText}> {item.Description}</Text>
</View>
)
renderHeader = ({ item }) => (
// Header View section - to display name of location
<View style={styles.headerContainer}>
{/* <Text style={styles.locationHeader}>Name of Place</Text> */}
<Text style={styles.locationHeader}>{item.name}</Text>
<Image source={require("../assets/upArrow.png")} style={styles.arrowLogo}></Image>
</View>
);
render() {
return (
<View style={styles.container}>
<MapView
provider={PROVIDER_GOOGLE}
ref={(map) => (this._map = map)}
showsUserLocation={true}
style={styles.map}
initialRegion={{
latitude: 48.84574344,
longitude: 2.325659581,
latitudeDelta: 0.155,
longitudeDelta: 0.155,
}}
>
{this.state.coordinates.map((marker, index) => (
<Marker
key={marker.name}
ref={(ref) => (this.state.markers[index] = ref)}
onPress={() => this.onMarkerPressed(marker, index)}
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
>
<Callout>
<Text>{marker.name}</Text>
</Callout>
</Marker>
))}
</MapView>
<View style={styles.bottomView}>
<LinearGradient
style={styles.gradient}
colors={["rgba(0, 0, 0,0)", "rgba(0, 0, 0,1)"]}
/>
</View>
<Carousel
ref={(c) => {
this._carousel = c;
}}
data={this.state.coordinates}
containerCustomStyle={styles.carousel}
renderItem={this.renderCarouselItem}
sliderWidth={Dimensions.get("window").width}
itemWidth={300}
removeClippedSubviews={false}
onSnapToItem={(index) => this.onCarouselItemChange(index)}
/>
<BottomSheet
ref={(c) => {
this._bottomsheet = c;
}}
data={this.state.coordinates}
renderItem={this.renderHeader}
contentPosition={this.trans}
snapPoints={[100, 400]}
renderContent={this.renderInner}
onSnapToItem={(index) => this.onCarouselItemChange(index)}
/>
</View>
);
}
}
const IMAGE_SIZE = 200
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
},
map: {
...StyleSheet.absoluteFillObject,
},
gradient: {
...StyleSheet.absoluteFillObject,
height: 5,
bottom: 0,
},
bottomView: {
width: "100%",
height: 25,
justifyContent: "center",
alignItems: "center",
position: "absolute",
bottom: 200,
},
carousel: {
position: "absolute",
bottom: 0,
marginBottom: 0,
backgroundColor: "#ececec",
height: 220,
},
cardContainer: {
backgroundColor: "rgba(0, 0, 0, 0.6)",
height: 200,
width: 300,
padding: 15,
borderRadius: 24,
marginTop: 10,
},
cardImage: {
height: 150,
width: 300,
bottom: 0,
position: "absolute",
borderBottomLeftRadius: 24,
borderBottomRightRadius: 24,
},
cardTitle: {
color: "white",
fontSize: 20,
alignSelf: "center",
},
cardDescription: {
color: "white",
fontSize: 18,
alignSelf: "flex-start",
},
headerContainer: {
width: '100%',
backgroundColor: '#ececec',
borderWidth: 0.5,
paddingVertical: 20,
justifyContent: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
},
locationHeader: {
fontSize: 18,
position: "relative",
fontWeight: "bold",
marginLeft: 15,
},
arrowLogo: {
height: 20,
width: 20,
opacity: 0.5,
marginRight: 15,
},
bottomSheetContainer: {
backgroundColor: 'white'
},
bottomSheetInnerContainer: {
width: "100%",
color: "white",
backgroundColor: "white",
height: 800
},
descriptionText: {
fontSize: 20,
paddingVertical: 30,
marginLeft: 20
}
});
我相信我的错误出现在 renderInner 和/或 renderHeader 函数中,但是在尝试了许多不同的方法后,我无法让它工作。
当我在renderHeader函数中注释掉这一行时:
<Text style={styles.locationHeader}>{item.name}</Text>
还有 renderInner 函数中的那一行:
<Text style={styles.descriptionText}> {item.Description}</Text>
除了呈现我想要的标题和描述之外,其他一切都很好。我收到此错误是否有原因?
【问题讨论】:
标签: javascript reactjs json react-native expo