繁体   English   中英

React Native - 组件未加载

[英]React Native - Components not loading

在 React Native 中遇到一个奇怪的问题 - 我正在尝试构建一个卡片列表,其中每张卡片代表一张带有用户信息(例如名字、姓氏等)的卡片。

卡片是一个单独的组件,它采用_id道具。 然后在 Card 组件中使用_id来获取数据。 然后像这样实例化卡片:

Card.js

import React, { useState, useEffect } from 'react';

import {
  View,
  Text,
  Image,
  StyleSheet
} from 'react-native';

const Card = (props) => {
   const [bio, setBio] = useState(true) 
   const [email, setEmail] = useState(true) 
   const [firstName, setFirstName] = useState(true) 
   const [lastName, setLastName] = useState(true) 
   const [phoneNumber, setPhoneNumber] = useState(true) 
   const [photoData, setPhotoData] = useState(true) 

   const baseUrl = "node-js-backend-url"
   const fileReaderInstance = new FileReader();
   
   loadImage = (url, headers) => {
      fetch(url, {headers})
      .then(response => response.blob())
      .then(blob => {
         fileReaderInstance.readAsDataURL(blob);
         fileReaderInstance.onload = () => {
            base64Data = fileReaderInstance.result;
            setPhotoData(base64Data);
         }
      })
      .then(() => {
         console.log("Card details: ")
         console.log(firstName)
         console.log(lastName)
      })
      .catch(error => {
         console.log("Error getting image for card: " + props._id + ", token: " + props.token+ ", "+ error)
      });
   }

   loadCardData = (url) => {
      let headers = new Headers()
      headers.append("Content-Type", "application/x-www-form-urlencoded");
      headers.append("x-auth-token", props.token)

      fetch(url, {headers})
      .then(response => response.json())
      .then(data => {
         setFirstName(data.firstName ? data.firstName : null)
         setLastName(data.lastName ? data.lastName : null)
         setBio(data.bio ? data.bio : null)
         setEmail(data.email ? data.email : null)
         setPhoneNumber(data.phoneNumber ? data.phoneNumber : null)

         var photoUrl = baseUrl + "/api/card/" + data._id + "/file/image/" + data.photo.filename;
         loadImage(photoUrl, headers)
      })
      .catch(error => {
         console.log("Error fetching card data for card: " + props._id + ", token: " + props.token + ", " + error)
         
      });
   }

   useEffect(() => {
         let url = baseUrl + "/api/card/" + props._id
         loadCardData(url)
         console.log("Successfully loaded card.")
   }, []);

  return (
    <>
         <View 
            style={cardStyles.outerView}
         >
            <View style={cardStyles.photoView}>
               <Image
                  source={{
                     uri: photoData.length > 0 ? photoData : null
                   }}
                   style={cardStyles.portrait}
               ></Image>
            </View>
            <View style={cardStyles.infoView}>
               <Text style={cardStyles.names}>{firstName} {lastName}</Text>
               <Text style={cardStyles.bio}>{bio}</Text>
               <Text style={cardStyles.contact}>{email}</Text>
               <Text style={cardStyles.contact}>{phoneNumber}</Text>
            </View>
         </View>
    </>
  );
};

const cardStyles = StyleSheet.create({
   outerView: {
      backgroundColor: '#F9F8F8',
      shadowColor: "#000",
      shadowOffset: {
         width: 0,
         height: 2,
      },
      shadowOpacity: 0.23,
      shadowRadius: 2.62,
      elevation: 4,
      borderRadius: 10,
      padding: 15,
      flexDirection: "row",
      justifyContent: "center",
      alignItems: "center"
   },
   names: {
      fontSize: 18,
      margin: 5
   },
   bio: {
      margin: 10
   },
   contact: {
      fontSize: 14
   },
   photoView: {
      flex: 0.425,
      width: 100,
      height: 100,     
      borderRadius: 250, 
      marginRight: 15,
      backgroundColor:"#FFFFFF",
      justifyContent: "center",
      alignItems: "center"
   },
   portrait: {
      flex: 1,
      width: "100%",
      height: "100%",
      resizeMode: 'contain',
      borderRadius: 100,
   },
   infoView: {
      flex: 1
   }
})

export default Card;

Connections.js

import React, { useState, useEffect } from 'react';
import { styles } from '../styles/styles'
import Card from '../components/Card'

import {
  SafeAreaView,
  View,
  ScrollView,
  Text,
  StatusBar,
  StyleSheet
} from 'react-native';

const ContactsPage: () => React$Node = () => {
  const baseUrl = "node-js-backend-url"
  const token = "[x-auth-token-for-testing]"
  
  const [connections, setConnections] = useState([]) 
  const [loading, setLoading] = useState() 

  loadConnections = () => {
    let headers = new Headers()
    headers.append("Content-Type", "application/x-www-form-urlencoded");
    headers.append("x-auth-token", token)

    let url = baseUrl + "user/connections"
    console.log("url: " + url)

    fetch(url, {headers})
    .then(response => response.json())
    .then(data => {
      setConnections(data.connections)
      setLoading(false)
    })
    .catch(error => {
        console.log("Error fetching connections: " + error)
    });
  }
  useEffect(() => {
    setConnections([])
    setLoading(true)
    loadConnections()
  }, []);

  return (
    <>
        <StatusBar barStyle="dark-content" />
        <SafeAreaView style={styles.container}>
          <View style={styles.heading}>
            <Text style={styles.headline}>Connections</Text>
          </View>
          <ScrollView style={styles.body, cardStyles.cardList}>
            {/* {loading == true && <Text>Loading...</Text>}
            {(loading == false && connections.length == 0) && <Text>You have no connections yet! Add some to get started...</Text>}
            {(loading == false && connections.length > 0) && connections.map(connection => (<Card key={connection} _id={connection} token={token}></Card>))} */}
            {/* {( loading == false  */}
              {/* <Card key="card1" _id="6005ef770aeb9b3a7035311f" token={token} style={cardStyles.card}></Card> */}
              {/* <Card key="card2" _id="6011d9d39689ab00049fc6e8" token={token} style={cardStyles.card}></Card> */}
              {/* <Card key="card3" _id="6005ef770aeb9b3a7035311f" token={token} style={cardStyles.card}></Card> */}
              <Card key="card4" _id="6011d9d39689ab00049fc6e8" token={token} style={cardStyles.card}/>
              <Card key="card5" _id="6005ef770aeb9b3a7035311f" token={token} style={cardStyles.card}/>
          </ScrollView>
        </SafeAreaView>
    </>
  );
};

const cardStyles = StyleSheet.create({
  card: {
    marginTop: 10,
    marginBottom: 10
  },
  cardList: {
    height: "80%"
 }
})

export default ContactsPage;

控制台记录卡片数据,可以看到卡片加载成功 连接页面截图

结果是渲染了 2 张卡片,但只有最后一张卡片包含任何信息。 如果我只创建一张卡片,所有信息都会按预期显示。 添加多于两张卡会导致除最后一张之外的所有卡都未填充(即不显示用户数据)。

有趣的是,即使对于不显示的卡片,也会加载正确的数据。 记录每张卡数据的检索显示用户数据已设置在 state 中。 此外,不应用卡片样式的边距。 这可能是什么情况,如何解决?

您将所有数据获取函数声明为全局变量(例如loadCardDataloadImageloadConnections ),因为您没有在它们前面添加像const这样的关键字来定义它们的 scope。

改成:

const loadCardData = (url) => 

并重复所有实例。

无关说明:您可能需要重新考虑对所有useState挂钩的默认 state 使用true 您稍后会进行真/假比较,最终将在值初始化之前返回true 考虑将它们初始化为类型的空版本,例如stringuseState("")或未定义的类型。

没有这个,他们 go 进入全局 scope 并最终仅捕获最后出现的setName

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM