Home > Net >  Error in working with useEffect for fetching data from an API
Error in working with useEffect for fetching data from an API

Time:12-21

I am learning React Native, and in following one of the live-coding sessions on YouTube I have come across the following problem. What I want to do is: I am making an app with expo and I want to fetch data from CoinGecko's free crypto API. My code is:

import React, { useState, useEffect } from "react";
import { View, Text, Image } from "react-native";
import axios from "axios";
const getCoinData = async (coinId) => {
  try {
    const response = await axios.get(
      `https://api.coingecko.com/api/v3/coins/${coinId}?community_data=false&developer_data=false`
    );
    return response.data;
  } catch (error) {
    console.log(error);
  }
};
const BugScreen = () => {
  const [coin, setCoin] = useState(null);

  useEffect(() => {
    const fetchCoinData = async () => {
      const fetchedCoinData = await getCoinData("bitcoin");
      setCoin(fetchedCoinData);
    };
    fetchCoinData();
  }, []);

  const {
    name,
    symbol,
    image: { small },
    market_cap_rank,
  } = coin;

  return (
    <View style={{ paddingHorizontal: 10 }}>
      <Text>{name}</Text>
      <Text>{symbol}</Text>
      <Image source={{ uri: small }} style={{ height: 25, width: 25 }} />
      <Text>{market_cap_rank}</Text>
    </View>
  );
};

export default BugScreen;

I get an error telling me null is not an object (evaluating 'coin.name'). I have also included a Screenshot of the error.

The way I understand it each time that the screen is rendered the useEffect() should run, and fetch the data, but the strange thing is that even when I add a 'console.log(coin) in the body of the 'fetchCoinData function, nothing is written on the console's screen.

It would be so kind of you if you could help me understand what's going wrong. Thank you.

CodePudding user response:

You initialise coin to be null so until the API call resolves, it remains null.

Perhaps a better option would be to initialise it to a placeholder object

const initialState = {
  name: "",
  symbol: "",
  image: {
    small: "https://via.placeholder.com/150"
  },
  market_cap_rank: ""
}

const BugScreen = () => {
  const [coin, setCoin] = useState({...initialState});

  // etc

CodePudding user response:

thank you for your help. Based on the @Phil's comment I did the following and it worked:

import React, { useState, useEffect } from "react";
import { View, Text, Image } from "react-native";
import axios from "axios";

const getCoinData = async (coinId) => {
  try {
    const response = await axios.get(
      `https://api.coingecko.com/api/v3/coins/${coinId}?community_data=false&developer_data=false`
    );
    return response.data;
  } catch (error) {
    console.log(error);
  }
};

const BugScreen = () => {
  const initialState = {
    name: "",
    symbol: "",
    image: "https://via.placeholder.com/150",
    marketCapRank: "",
  };
  const [coin, setCoin] = useState(initialState);

  useEffect(() => {
    const fetchCoinData = async () => {
      const fetchedCoinData = await getCoinData("bitcoin");
      const fetchedData = {
        name: fetchedCoinData.name,
        symbol: fetchedCoinData.symbol,
        image: fetchedCoinData.image.small,
        marketCapRank: fetchedCoinData.market_cap_rank,
      };
      setCoin((coin) => {
        return { ...coin, ...fetchedData };
      });
    };
    console.log(coin);
    fetchCoinData();
  }, []);

  const { name, symbol, image, marketCapRank } = coin;

  return (
    <View style={{ paddingHorizontal: 10 }}>
      <Text style={{ color: "white" }}>{name}</Text>
      <Text style={{ color: "white" }}>{symbol}</Text>
      <Image source={{ uri: image }} style={{ height: 25, width: 25 }} />
      <Text style={{ color: "white" }}>{marketCapRank}</Text>
    </View>
  );
};

export default BugScreen;
  • Related