1

I have an error when I call an API, I think this error is failed to compile, because this error indicates to me:

Cannot read property 'type' of undefined in line 18

I run fetchCoins in useEffect, how to I can solve this error? I dont know why fetchCoins is undefined!?

import './App.css';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Coin from './Coin';
import Pagination from 'react-js-pagination'

const App = () => {

  const [coins,setCoins] = useState([]);
  const [search , setSearch] = useState('');

  const [loading, setLoading] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [postsPerPage] = useState(10);


useEffect(() => {
  const fetchCoins = () => {
    setLoading(true);
    axios.get('https://api............')
    .then(res => { setCoins(res.data)})
    .catch(err => console.log(err))
    setLoading(false);
  };
  fetchCoins()
}, [])


  const handleChange = e => {
    setSearch(e.target.value)
  }

  const filteredCoins = coins.filter(coin =>
    coin.name.toLowerCase().includes(search.toLowerCase())
    );

  console.log(fetchCoins())

  return (
    <div className="coin-app">
      <div className="coin-search"> 

      <form>
        <input type="text" placeholder="search" className="coin-input" onChange={handleChange} />
      </form>
    </div>
    {filteredCoins.map(coin => {
        return (
          <Coin
            key={coin.id}
            name={coin.name}
            price={coin.current_price}
            symbol={coin.symbol}
            marketcap={coin.total_volume}
            volume={coin.market_cap}
            image={coin.image}
            priceChange={coin.price_change_percentage_24h}
          />
        );
      })}

    </div>
  );
}

export default App;
6
  • 1
    Can you share line 18 please? You're calling a type property of an undefined object and I can't see that in your code Commented Nov 4, 2020 at 21:14
  • You can't call console.log(fetchCoins()) outside your useEffect because you used const which is block scoped. Read more here: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Nov 4, 2020 at 21:15
  • 1
    I would think that setLoading(false) would happen almost immediately after setLoading(true) due to the async nature of the part in between. Commented Nov 4, 2020 at 21:17
  • Yeah there are many issues here I can't focus on one :D Commented Nov 4, 2020 at 21:17
  • 1
    I think it's line 18 of some other file. There is nothing here with a .type property. Commented Nov 4, 2020 at 21:18

1 Answer 1

1

You don't have access to fetchCoins outside useEffect because of cost block scope. Read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block

You can fix that bit via the below code.

Your error around line 18 is not in this file and likely unrelated to your question.

import "./App.css";
import React, { useState, useEffect } from "react";
import axios from "axios";
import Coin from "./Coin";
import Pagination from "react-js-pagination";

const App = () => {
  const [coins, setCoins] = useState([]);
  const [search, setSearch] = useState("");

  const [loading, setLoading] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [postsPerPage] = useState(10);

  useEffect(() => {
    const fetchCoins = () => {
      setLoading(true);
      axios
        .get("https://api............")
        .catch((err) => console.log(err))
        .then((res) => {
          setCoins(res.data);
          setLoading(false); // note I moved this in here
        });
    };
    fetchCoins();
  }, []);

  const handleChange = (e) => {
    setSearch(e.target.value);
  };

  const filteredCoins = coins.filter((coin) =>
    coin.name.toLowerCase().includes(search.toLowerCase())
  );

  console.log(coins); // you don't have access to fetchCoins here due to block scope limitations

  return (
    <div className="coin-app">
      <div className="coin-search">
        <form>
          <input
            type="text"
            placeholder="search"
            className="coin-input"
            onChange={handleChange}
          />
        </form>
      </div>
      {filteredCoins.map((coin) => {
        return (
          <Coin
            key={coin.id}
            name={coin.name}
            price={coin.current_price}
            symbol={coin.symbol}
            marketcap={coin.total_volume}
            volume={coin.market_cap}
            image={coin.image}
            priceChange={coin.price_change_percentage_24h}
          />
        );
      })}
    </div>
  );
};

export default App;
Sign up to request clarification or add additional context in comments.

1 Comment

move setLoading(false) inside .then promise and it was fixed, thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.