React Native – 组件中的fetch问题

huangapple go评论65阅读模式
英文:

React Native - Problem with fetch into a component

问题

I understand that you're facing an issue with your React Native application related to fetching and displaying data from a server. It appears that there might be a problem with handling the token data.

Here are some steps you can take to troubleshoot and understand the issue:

  1. Make sure you have the necessary dependencies installed and properly configured, such as React Navigation and your context providers.

  2. Check if the token variable in your TokenDetail component is being initialized correctly. It seems to be initially set to null, which could lead to the "Cannot read property 'name' of null" error. Ensure that token has a valid value before trying to access its properties.

  3. Verify that the API request in the StackTokenDetail component is returning data as expected. You can add some console logs to check the response and ensure that it contains the necessary information.

  4. Ensure that the StackTokenDetail component is receiving the correct route.params.id. Verify that this value is being passed correctly from your list component.

  5. In the TokenDetail component, when displaying the description, make sure that token.description is not null or undefined. You might want to add conditional checks to ensure you're only trying to display the description when it exists.

  6. Check for any issues with navigation. Ensure that navigating back to the list and selecting a different item works as expected without causing crashes.

  7. Consider using try-catch blocks when making API requests to handle potential errors more gracefully and log any errors for debugging purposes.

  8. If the issue persists, you can provide more specific error messages or logs to help pinpoint the problem further.

Remember to thoroughly test each component and step in your code to identify where the issue occurs. Debugging and logging can be valuable tools in troubleshooting these kinds of problems.

英文:

I got a problem I can not understand.

I tried to close the App and Expo in Terminal, launch again.
Search on a Google.
I tried many things, but still I got a strange things.

So, I have a list of items (crypto-asset) and when I select one of them, a new window appears with details of this token. Simple.

Here is my "FlatList" :

import { useContext, useEffect, useState } from 'react'
import { Alert, FlatList, View } from 'react-native'
import { SettingsContext } from '../../contexts/SettingsContext'
import ItemToken from '../ItemToken/ItemToken'

export function TokenList() {
  const { currency } = useContext(SettingsContext)
  const [listToken, setListToken] = useState(null)
  const [refreshing, setRefreshing] = useState(false)

  useEffect(() => {
    getListTokens()
  }, [currency])

  useEffect(() => {
    if (refreshing) {
      getListTokens()
      setRefreshing(false)
    }
  }, [refreshing])

  /**
   * For the currency, never mind, it's just Boolean to get things done, it's not the final code.
   */
  function getListTokens() {
    fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${
      currency ? 'usd' : 'eur'
    }&order=market_cap_desc&per_page=100`)
      .then(response => response.json())
      .then(json => setListToken(json))
      .catch(error => Alert.alert('CoinGecko API Error', error))
    }

return (
  <FlatList
    data={listToken}
    keyExtractor={item => item.id}
    onRefresh={() => setRefreshing(true)}
    refreshing={refreshing}
    renderItem={
      ({ item }) =>
        <ItemToken item={item} />
    }
    ItemSeparatorComponent={<View style={{ height: 1, opacity: 0.6 }} />}
  />
  )
}

My ItemToken (without CSS) :

import { useContext, memo } from 'react'
import { View, Text, Image, TouchableOpacity, StyleSheet } from 'react-native'
import { SettingsContext } from '../../contexts/SettingsContext'
import { NavigationContext } from '@react-navigation/native'

function ItemToken({ item }) {
  const { currency } = useContext(SettingsContext)
  const { navigation } = useContext(NavigationContext)

  return (
    <TouchableOpacity style={styles.button} onPress={() => navigation.navigate('StackTokenDetail', { id: [item.id] })}>
      <View>
        <Image style={styles.image} src={item.image} />
      </View>
      <View style={styles.mainSection}>
      <Text style={styles.fontStyle}>{item.name}</Text>
      <Text>{currency ? '$' : null}{item.current_price}{currency ? null : '€'}</Text>
      </View>
    </TouchableOpacity>
  )
}

Ok, this it's ok.

Here my component to display the detail of the token.
It's here where I get my problems.

import { useEffect, useState } from 'react'
import { SafeAreaView, ScrollView } from 'react-native'
import TokenDetail from '../../TokenDetail/TokenDetail'

export function StackTokenDetail({ route }) {
  const [token, setToken] = useState(null)

  useEffect(() => {
    fetch(`https://api.coingecko.com/api/v3/coins/${route.params.id}`)
      .then(response => response.json())
      .then(json => setToken(json))
      .catch(e => console.error(e))
  }, [])

  return (
    <SafeAreaView>
      <ScrollView style={{ flex: 1, padding: 40 }}>
        <TokenDetail token={token} />
      </ScrollView>
    </SafeAreaView>
  )
}

And my detail stack page:

import { memo } from 'react'
import { Text } from 'react-native'

function TokenDetail({ token }) {
  console.log('tokenDetail token:', token.name)
  console.log('tokenDetail token:', token.symbol.toUpperCase())
  console.log('tokenDetail token:', token.description.en)

  return (
    <>
      <Text style={{ fontWeight: 600, paddingBottom: 20 }}>{token.symbol.toUpperCase()} - {token.name}</Text>
      <Text>{token.description.en}</Text>
    </>
  )
}

export default memo(TokenDetail)

Well when I start from the list and select an item, I got this error: "Cannot read property 'name' of null.

OK

But, if I delete all lines with the token from JSON in the last component, save and refresh. I select again an item and display the screen. Normal you will say. Right!

But if I put my lines again, save, refresh, then my all console.log will display the informations I get from the server. Everything is here and works. Event the App display the symbol and the name, but not the description (which I got a hours ago).

If I click on the back button, return to the list and select an item (the same one or a different), then crash again...

Please, can you help me to understand?

Also it's why I create a new component for the display the informations and use a memo.

Thank you.

I try to get some data from a server, which doesn't work.

答案1

得分: 1

这个问题是因为在<TokenDetail token={token} />行危险地传递了token值,尽管它的值为空。在TokenList组件的开头,您使用const [token, setToken] = useState(null)来定义状态。也许您可以在这里采取两种方法来解决这个问题。

解决方案1:
在token值不为空之前(通常在您进行的API调用后发生)不显示TokenDetail组件。请参阅下面的代码:

return (
    <SafeAreaView>
      <ScrollView style={{ flex: 1, padding: 40 }}>
        {token ? <TokenDetail token={token} /> : null}
      </ScrollView>
    </SafeAreaView>
)

解决方案2:
以安全的方式在TokenDetail内部访问token值,使用可选链接技术。

function TokenDetail({ token }) {
  console.log('tokenDetail token:', token?.name)
  console.log('tokenDetail token:', token?.symbol?.toUpperCase())
  console.log('tokenDetail token:', token?.description?.en)

  return (
    <>
      <Text style={{ fontWeight: 600, paddingBottom: 20 }}>{token ? `${token.symbol.toUpperCase()} - ${token.name}` : ""}</Text>
      <Text>{token ? token.description.en : ""}</Text>
    </>
  )
}
英文:

This issue is because you are dangerously passing the token value at <TokenDetail token={token} /> line even though its value is null. At the start of the TokenList component, you define state using const [token, setToken] = useState(null). May be you can do two things here to resolve this issue.

Solution 1:
Do not show the TokenDetail component till the token value is not null(Which eventually happens after the API call you are making. See the code below

return (
    <SafeAreaView>
      <ScrollView style={{ flex: 1, padding: 40 }}>
        {token ? <TokenDetail token={token} /> : null}
      </ScrollView>
    </SafeAreaView>
)

Solution 2:
Access the token value inside the TokenDetail in a safe manner using the optional chaining technique.

function TokenDetail({ token }) {
  console.log('tokenDetail token:', token?.name)
  console.log('tokenDetail token:', token?.symbol?.toUpperCase())
  console.log('tokenDetail token:', token?.description?.en)

  return (
    <>
      <Text style={{ fontWeight: 600, paddingBottom: 20 }}>{token ? {{token.symbol.toUpperCase()} - {token.name}} : ""}</Text>
      <Text>{token ? token.description.en : ""}</Text>
    </>
  )
}

huangapple
  • 本文由 发表于 2023年6月8日 22:29:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76432904.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定