在 React Native Expo 中将项目渲染到底页时出现类型错误

Posted

技术标签:

【中文标题】在 React Native Expo 中将项目渲染到底页时出现类型错误【英文标题】:Type Error When Rendering Item to Bottomsheet in React Native Expo 【发布时间】: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>

除了呈现我想要的标题和描述之外,其他一切都很好。我收到此错误是否有原因?

【问题讨论】:

【参考方案1】:

底部表格中没有数据!

当您调用 renderItem 时,您必须传递单个坐标!

例如:

renderItem=() =&gt; this.renderHeader(this.state.coordinates[0])

【讨论】:

即使我尝试这样做,我也没有收到错误,但它不会呈现任何内容。 'renderContent=() => this.renderInner(this.state.coordinates[0])` 到目前为止,我已经尝试了很多不同的方法,但没有成功

以上是关于在 React Native Expo 中将项目渲染到底页时出现类型错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在expo react native App中将api级别29更改为30

未处理的承诺拒绝:TypeError:网络请求失败 - 在 React Native / Expo 中将 Base64(视频/mp4)转换为 Blob

尝试在 create-react-native-app 项目 (expo) 中使用 react-native-fs

react-native-permissions 在 react-native expo 项目中返回 RNPermissions null

如何使用搜索文本输入(expo、react-native)在屏幕上显示项目

为啥 React-Native 无法在与 Expo 的 Android 连接上启动项目?