Exercise - Refresh the Prices on Click

Welcome to the thread for the exercise Refresh the prices on Click

Coding exercise: Refresh the price of the coin upon clicking the Refresh button on the line of the coin.

FYI for doing name changes on a variable you can press F2 and VS code will change all the references for you.

App.js - Refresh Prices
  • I moved the API calls into separate functions
  • Call the API instead of calculating a random price change
  • The tricky part was using await Promise.all() as the API call turns the mapping into promises. You get undefined errors in the Coin component without it.
const API_BASE_URL = 'https://api.coinpaprika.com/v1';

  getCoinPrice = (id) => {
    return axios.get(`${API_BASE_URL}/tickers/${id}`);
  }

  handleRefresh = async (valueChangeticker) => {
    // generate the new state by cloning the old state
    // and updating the target coin price
    const responses = this.state.coinData.map(async values => {
      let newValues = { ...values }; // shallow copy
      
      if (values.ticker === valueChangeticker) {
        const response = await this.getCoinPrice(values.key);
        newValues.price = response.data.quotes['USD'].price;
      }

      return newValues;
    });
    const newCoinData = await Promise.all(responses);

    this.setState({ coinData: newCoinData });
  }

1 Like

Coding exercise: Refresh the price of the coin upon clicking the Refresh button on the line of the coin.

I modified the handleRefresh function to get and refresh the price with an api call for a specific coin id. To lift up the id from Coin to App, and as i can’t use key as props, in coinList i passed the id value to the Coin component. Thus Coin has a props.id that it can passed to App when the button is clicked.

App.js
import React from 'react';
import ExchangeHeader from './components/ExchangeHeader/ExchangeHeader';
import CoinList from './components/CoinList/CoinList';
import AccountBalance from './components/AccountBalance/AccountBalance';
import styled from 'styled-components';
import axios from 'axios';


const DivApp = styled.div`
    text-align: center;
    background-color: rgb(20, 56, 97);
    color: #cccccc;
    `;


const COIN_COUNT = 10;
const coinsUrl = 'https://api.coinpaprika.com/v1/coins';
const tickerUrl = 'https://api.coinpaprika.com/v1/tickers/';

class App extends React.Component {
  state = {
    balance: 10000,
    showBalance: true,
    coinData: [ ]
    
  }

  componentDidMount = async () => {
    const response = await axios.get( coinsUrl );
    const coinIds = response.data.slice(0, COIN_COUNT).map( coin => coin.id );

    const promises = coinIds.map( id => axios.get( tickerUrl + id ));
    const coinData = await Promise.all( promises );

    const coinPriceData = coinData.map( function(response) {
      const coin = response.data;
      //debugger;
      return {
        key: coin.id,
        name: coin.name,
        ticker: coin.symbol,
        balance: 0,
        price: parseFloat(Number( coin.quotes["USD"].price ).toFixed(2)) 
      };
    });

    this.setState({ coinData: coinPriceData });
  }


handleRefresh = async (valueChangekey) => {
  const keyData =  await axios.get( tickerUrl + valueChangekey);
  
  const newCoinData = this.state.coinData.map( function( values ) {
    let newValues = {...values};
    if (values.key === valueChangekey) {
      newValues.price = parseFloat(Number( keyData.data.quotes["USD"].price ).toFixed(2));
    };
  
  return newValues;
  });
  this.setState({ coinData: newCoinData });
}


  handleToggleBalance = () => {
    this.setState( function(oldState) {
      return {
        ...oldState,
        showBalance: !oldState.showBalance 
      };
    });
  }

  render() {
    return (
      <DivApp>
        <ExchangeHeader />
        <AccountBalance 
          amount={this.state.balance}
          handleToggleBalance={this.handleToggleBalance} 
          showBalance={this.state.showBalance} />
        <CoinList 
          coinData={this.state.coinData}
          handleRefresh={this.handleRefresh}
          showBalance={this.state.showBalance} />
      </DivApp>
    );
  }
}

export default App;
CoinList.jsx
import React, { Component } from 'react';
import Coin from '../Coins/Coin';
import styled from 'styled-components';


const Table = styled.table`
    margin: 50px auto 50px auto;
    display: inline-block;
    font-size: 1.4rem;
    `;

export default class CoinList extends Component {
    render() {
      /*
        const toggleBalance = this.props.showBalance ?
        <th>Balance</th> : null;
      */

        return (
            <Table> 
            <thead>
              <tr>
                <th>Name</th>
                <th>Ticker</th>
                {this.props.showBalance ? <th>Balance</th> : null}
                <th>Price</th>
                <th>Action</th>
              </tr>
            </thead>
            <tbody>
              {
                this.props.coinData.map( ({key, name, ticker, balance, price}) =>
                  <Coin 
                  key={key} 
                  id={key}
                  name={name} 
                  handleRefresh={this.props.handleRefresh}
                  ticker={ticker}
                  showBalance={this.props.showBalance}
                  balance={balance}
                  price={price} 
                  />
                )
              }
            </tbody>
          </Table>
        )
    }
}```
Coin.jsx
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const Td = styled.td`
    border: 1px solid #cccccc;
    width: 25vh;
`;
const Button = styled.button`
    height: 2rem;
    width: 100%;
    background-color: #282c34;
    color: #61dafb;
    border: none;
    font-size: 1rem;
    :active {
        background: #0053ba;
    }
    :hover {
        border: 1px solid #cccccc;
        border-radius: 3px;
        cursor: pointer;
    }
`;

export default class Coin extends Component {
    handleClick = (event) => {
        // Prevent the default action of submitting the form
        event.preventDefault();
        this.props.handleRefresh(this.props.id);
    }
    render() {
            return(
                <tr>
                  <Td>{this.props.name}</Td>
                  <Td>{this.props.ticker}</Td>
                  {this.props.showBalance ? <Td>{this.props.balance}</Td> : null}
                  <Td>${this.props.price}</Td>
                  <Td>
                      <form action="">
                          <Button onClick={this.handleClick}>Refresh</Button>
                      </form>
                  </Td>
                </tr>
              );
    }
}

Coin.propTypes = {
    name: PropTypes.string.isRequired,
    ticker: PropTypes.string.isRequired,
    price: PropTypes.number.isRequired
}
2 Likes
App.js handleRefresh fragment
  handleRefresh = async (coinId) => {
    const coin = await axios.get(`https://api.coinpaprika.com/v1/tickers/${coinId}`);
    const newCoinData = this.state.coinData.map((values) => {
      let newValues = { ...values };
      if (coinId === values.key) {
          newValues.price = parseFloat(Number(coin.data.quotes.USD.price).toFixed(4));
      }
      return newValues;
    });
    this.setState({ coinData: newCoinData });
  }
1 Like

so many talented people in here! looking over some of the code others came up with and I hope to be as good with mine some day! I feel so blessed and fortunate to have discovered Ivan On Tech!

3 Likes

I modified the code so refresh goes out to coin geko and gets the latest price. The code works but I dont like the code. I got lost in the this, this.protoype and bind and was constantly having my routines and variables being undefined at runtime, but finally got it running. Does any one have opinion on this code?, how should I do it better and cleaner?

import React, { Component } from 'react'
 import './Coin.css';
 import PropTypes from 'prop-types';

 const coingeckoService = require('../../services/coingeko-service');
 
 export default class Coin extends Component {
     constructor(props) {
         super(props);
         this.state = {
             price: this.props.price
         }

         // tricky dicky sht. the following statement is the way we connect the member function
         // handleClick() to the class.
         this.handleClick = this.handleClick.bind(this); 
     }
     
     
     render() {
         return (
            <tr className="coin-row">
                <td>{this.props.name}</td>
                <td>{this.props.ticker}</td>
                <td>${this.state.price}</td>
                <td>
                    <button onClick={this.handleClick}>Refresh</button>
                </td>
            </tr>
         )
     }

     /**
      * Come here when you need to process a mouse click event on the refresh coin button.
      * @param {*} event 
      */
     handleClick(event) {
        event.preventDefault();
        console.log("this.props.ticker=", this.props.ticker);
        
        this.getPriceQuoteFromCoingeko( this, this.props.ticker, (response)=> {
            // kind of a useless call back function here.
            console.log("returned from getting data from geko and updating it");
        });
     }
     
 }  //endCoin

 // data member requirements and type.
 Coin.protoType = {
     name: PropTypes.string.isRequired,
     ticker: PropTypes.string.isRequired,
     price: PropTypes.number.isRequired
 }

 /**
  * get all the prices from geko service. 
  * @param {*} callback 
  */
 Coin.prototype.getPricesFromCoingeko = function (callback) {
    console.log("getting prices");
   
    coingeckoService.getPriceQuotes((response) => {
        console.log("geko response=", response);  
        callback(response);
    })
    
 }

 /**
  * when mouse click we come here to get a fresh quote from geko for a particular coin.
  * then set the state for that coin.
  * 
  * @param {*} thisThing a pointer to the coin object so I can update the state
  * @param {*} ticker       
  * @param {*} callback     call this with the results.
  */
 Coin.prototype.getPriceQuoteFromCoingeko = function (thisThing, ticker, callback) {
    console.log("getting price for ", ticker);

    let gekocoinid = coingeckoService.getTickerFromName(ticker);
    console.log( "gekoid=", gekocoinid);
   
    console.log("what is thisThing", thisThing);  
    coingeckoService.getPriceQuote(gekocoinid, (response) => {
        console.log("maded it back from geko call",response);
        console.log(response.currency, response.usd);
        console.log("what is thisThing", thisThing);  
        thisThing.setState( function (oldState) {
            return { 
                price: response.usd
            }
        }); 
        callback(response);
    });
    
 }
1 Like

app.js :

// update the price, leave all the other things the same
handleRefresh = async(valueChangedTicker) => {
const response = await axios.get(tickerURL + valueChangedTicker);
const newCoinPriceData = response.data;
const newCoinData = this.state.coinData.map(function(coin) {
let newCoin = coin;
if ( coin.coinid === valueChangedTicker) {
newCoin.price = newCoinPriceData.quotes.USD.price;
console.log("refresh ", valueChangedTicker, “new price=”, newCoin.price);
}
return newCoin;
});
this.setState({coinData: newCoinData});
}

You can remove the binding you indicated as “tricky dicky sht” if your event handler is an arrow function instead of a simple function reference. Why? Because arrow functions auto-bind the context.

There are two choices to do this:

  1. Class properties:
handleClick = (event) => { ... }
  1. Creating an arrow function in the binding (less advised)
<button onClick={(e) => this.handleClick(e)}>Refresh</button>
1 Like

Spent a few hours going through trying to work out what I’d missed (looked on here and still couldn’t find it). It wasn’t until watching the solution video when the mistake was made on
“if ( valueChangeId === values.key )”
that I realised I had values.id rather than .key :sweat_smile:

I had actually used the right thing earlier on, but no change in price when I refreshed made me think I had it wrong, so I changed it :grimacing:

App
import React from "react";
import CoinList from './Components/CoinList/CoinList';
import AccountBalance from './Components/AccountBalance/AccountBalance';
import Header from './Components/Header/Header';
import styled from 'styled-components';
import axios from 'axios';
const Div = styled.div`
text-align: center;
background-color: rgb(20, 56, 97);
color: #cccccc;
`;

const COIN_COUNT = 10;
const tickerUrl = 'https://api.coinpaprika.com/v1/tickers/';

class App extends React.Component {

  state = {
    balance: 10000,
    showBalance: false,
    coinData: []
  }

  componentDidMount = async () => {
    let response = await axios.get('https://api.coinpaprika.com/v1/coins')
    let coinIds = response.data.slice(0, COIN_COUNT).map(coin => coin.id);
    const promises = coinIds.map(id => axios.get(tickerUrl + id));
    const coinData = await Promise.all(promises)
    const coinPriceData = coinData.map(function(response){
      const coin = response.data;
      return{
        key: coin.id,
        name: coin.name,
        ticker: coin.symbol,
        balance: 0,
        price: parseFloat(Number(coin.quotes['USD'].price).toFixed(2)),
      };
    });
    this.setState({coinData: coinPriceData });
  }
  handleRefresh = async (valueChangeId) => {
    let response = await axios.get(tickerUrl + valueChangeId);
    const refreshedData = response.data;
    const newCoinData = this.state.coinData.map( function( values ) {
      let newValues = {...values};
      if (valueChangeId === values.key) {
        newValues.price = parseFloat(Number(refreshedData.quotes['USD'].price).toFixed(2));
      }
      return newValues;
    });
    this.setState({ coinData: newCoinData });
  }
  handleToggleBalance = () => {
    this.setState({showBalance: ! this.state.showBalance});
  }
  render() {
    return (
      <Div>
        <Header/>
        <AccountBalance amount= {this.state.balance} showBalance={this.state.showBalance}
          handleToggleBalance = {this.handleToggleBalance} />
        <CoinList coinData={this.state.coinData} handleRefresh={this.handleRefresh}
          showBalance = {this.state.showBalance} />
      </Div>
    );
  }
}
export default App;
CoinList
import React, { Component } from 'react';
import Coin from '../Coin/Coin';
import styled from 'styled-components';

const Table = styled.table`
margin: 50px auto 50px auto;
display: inline-block;
font-size:1.4rem;
`;

export default class CoinList extends Component {
    render() {
        let balanceToggle = this.props.showBalance ? <th> Balance </th> : null;
        return (
            <Table>
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Ticker</th>
                    <th>Price</th>
                    {balanceToggle}
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>
            {
                this.props.coinData.map ( ({key, name, ticker, price, balance}) => 
                    <Coin 
                        key= {key} 
                        id = {key}
                        handleRefresh={this.props.handleRefresh}    
                        showBalance = {this.props.showBalance}
                        name={name} 
                        ticker={ticker}
                        balance= {balance}   
                        price={price} />
                )
            }
            </tbody>
            </Table>
        )
    }
}
Coin
import React, { Component } from "react";
import PropTypes from "prop-types";
import styled from 'styled-components';

const Td = styled.td`
    border: 1px solid #cccccc;
    width: 25vh;
`;

export default class Coin extends Component {

   handleClick = (event) => {
        //prevent default acton of submitting the form
        event.preventDefault();
        this.props.handleRefresh(this.props.id);
   }
   
    render() {
        let balanceToggle = this.props.showBalance ? <Td> {this.props.balance} </Td> : null;
        return (
            <tr>
                <Td>{this.props.name}</Td>
                <Td>{this.props.ticker}</Td>
                <Td>${this.props.price}</Td>
                {balanceToggle}
                <Td>
                    <form action="#" method="POST">
                        <button onClick={this.handleClick}>Refresh</button>
                    </form>
                </Td>
            </tr>
        )
    }
}

Coin.propTypes = {
    name: PropTypes.string.isRequired,
    ticker: PropTypes.string.isRequired,
    price: PropTypes.number.isRequired
}
1 Like
Coinlist.jsx
export default class CoinList extends Component {
    render() {
        return (
        <Table>
            <thead>
              <tr>
                <th>Name</th>
                <th>Ticker</th>
                <th>Price</th>
                {this.props.showBalance ? <th>Balance</th> : null}
                <th>Actions</th>
              </tr>
          </thead>
          <tbody>
            {this.props.coinData.map(({key, name, ticker, price, balance}) =>{
             return <Coin key={key} id={key} handleRefresh={this.props.handleRefresh} showBalance={this.props.showBalance} name={name} ticker={ticker} balance={balance} price={price}></Coin>
            })
            }
          </tbody>
        </Table>
        )
    }
}

Coin.jsx
export default class Coin extends Component {

     state = {
            price: this.props.price
        }


    handleClick = (event) =>{
        event.preventDefault();

        this.props.handleRefresh(this.props.id);

    }
    render() {
        return (
        <tr>
            <Td>{this.props.name}</Td>
            <Td>{this.props.ticker}</Td>
            <Td>${this.props.price}</Td>
            {this.props.showBalance ? <Td>{this.props.balance}</Td> : null}
            <Td>
                <form action="#" method="POST">
                <button onClick={this.handleClick}>Refresh</button>
                </form>
            </Td>
        </tr>
        );
    }
}

App.js

  handleRefresh = async (coin_id) => {
    const url = 'https://api.coinpaprika.com/v1/tickers/' + coin_id;
    const response = await axios.get(url);
    const coinResponse = response.data;

    const newCoinData = this.state.coinData.map(values => {
      let newValues = {...values};
      if(coin_id === newValues.key){
        const newPrice = parseFloat(Number(coinResponse.quotes.USD.price).toFixed(4));
        newValues.price = newPrice;
      }
      return newValues;
    })
  
    this.setState({coinData: newCoinData});
  }
1 Like

Added the tickerId in both Coin.jsx and CoinList.jsx in order to call the handler with the relevant parameter. I made the same mistake that was shown in the video, not updating values.id to values.key in the control-flow wondering why my code wasn’t updating. I figured that the API wasn’t supplying a new price as often as I clicked the button, but when the price changed I still didn’t have newCoinData updated.

So I watched the solution, got the key corrected and boom, it worked. :slight_smile:

App.js
  handleRefresh = async (tickerId) => {
    const response = await axios.get(`https://api.coinpaprika.com/v1/tickers/${tickerId}`);
    const newPrice = formatPrice(response.data.quotes.USD.price);
    const newCoinData = this.state.coinData.map((values) => {
      let newValues = { ...values };
      if (tickerId === values.key) {
        newValues.price = newPrice;
      }
      return newValues;
    });
    this.setState({coinData: newCoinData});
  }

2 Likes

It took unnecessary amount of time for me to solve this. I tried to use the key but it gave me an error that it is not a prop. Of course I insisted that key is a prop. After a few hours of failing, I submitted to the error message and created a new prop with the name “url” and assigned the key value to it. It worked.

App.js
handlePrice = async (tickerChange ,url) => {

    let priceData = await axios.get("https://api.coinpaprika.com/v1/tickers/" + url);
    const newCoin = this.state.coinData.map( function( {balance,ticker,name,price,key} ) {
      let newPrice = price;
      if (tickerChange === ticker) {
          
        newPrice = priceData.data.quotes.USD.price;
        console.log(newPrice);
        console.log(url);
        }
        return {
          price : newPrice,
          balance,
          ticker,
          name,
          key,
        }
});
CoinList.jsx:
{ this.props.coinData.map( ({key,name,ticker,price,balance}) => 
            <Coin 
             key={key} 
             url={key} 
             name={name} 
             ticker={ticker} 
             price={price} 
             balance={balance} 
             showBalance = {this.props.showBalance} 
             handlePrice={this.props.handlePrice}/> )
            }
Coin.jsx
click(event) {
        event.preventDefault();
        this.props.handlePrice(this.props.ticker, this.props.url);
    }
1 Like
App.js
  handleRefresh = async (coinID) => {
    const coinPromise = await axios.get(`https://api.coinpaprika.com/v1/tickers/${coinID}`);
    const coinPrice = coinPromise.data.quotes.USD.price;
    const newCoinData = this.state.coinData.map( ( values ) => {
      let newValues = { ...values };
      if(coinID === newValues.key) {
        newValues.price = parseFloat(Number(coinPrice).toFixed(4));
      }
      return newValues;
    });
    
    this.setState({ coinData: newCoinData });
  }
CoinList.jsx
this.props.coinData.map( ({key, name, ticker, price, balance}) =>
                <Coin key={key}
                      id={key}
                      handleRefresh={this.props.handleRefresh}
                      showBalance={this.props.showBalance}
                      name={name} 
                      ticker={ticker} 
                      balance={balance}
                      price={price} />
              )
Coin.jsx
handleClick = (event) => {
        event.preventDefault();
        this.props.handleRefresh(this.props.id);
    }
2 Likes

This is my solution . I passed another data
id: coin.id, because I have problems with key: coin.id. Its working.
:grinning: :grinning:
App.js

import CoinList from './components/CoinList/CoinList';
import AccountBalance from './components/AccountBalance/AccountBalance';
import React  from 'react';
import ExchangeHeader from './components/ExchangeHeader/ExchangeHeader';
import styled from 'styled-components'
import axios from 'axios'; 


const COINCOUNT = 10; 
const ContainerAll = styled.div`
    background-color: #282c34;
    height: 10;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-size: calc(20px + 2vmin);
    color: white;
    `


class App extends React.Component {
  state = { 
       balance : 20000, 
       showBalance : true,
       coinData :[ ] 
    }
    

  handleRefresh = async (keyid) => {  // receive the id with keyid
    const promise = await axios.get('https://api.coinpaprika.com/v1/tickers/'+ keyid);
    const newCoinData = this.state.coinData.map((values) => { 
    let newValues = {...values}; 
      if (keyid=== values.key) {
        const updatePrice = parseFloat(Number(promise.data.quotes.USD.price).toFixed(4)); // took directly the price
        console.log(`Coin = ${values.name} Ticker: ${values.ticker} Update price ${updatePrice} `) // to check in console
        newValues.price =  updatePrice;  // update price 
      }
      return newValues
    }); 
      this.setState({coinData: newCoinData}) // the end
  }
      

  handleBalanceVisibilityChange = () =>{ 
    this.setState(function(oldState){ 
      return {
        ...oldState, 
        showBalance: !oldState.showBalance
      }
    })
  }


  componentDidMount = async () => { 
    const response = await axios.get('https://api.coinpaprika.com/v1/coins'); 
    const coinIds = response.data.slice(0, COINCOUNT).map(coin=> coin.id);
    const tickerUrl = 'https://api.coinpaprika.com/v1/tickers/';
    const promises = coinIds.map(id =>axios.get(tickerUrl + id)); 
    const coinData =  await Promise.all(promises);
    const coinPriceData = coinData.map((response) =>{
        const coin = response.data; 
        return {
         key: coin.id, 
         id: coin.id,// New i cannot use key
         name: coin.name,
         ticker:coin.symbol,
         balance: 0, 
         price: parseFloat(Number(coin.quotes.USD.price).toFixed(4)),
      };
    }); 
    this.setState({coinData: coinPriceData});
  }


render() {
    return (
    <ContainerAll>
      <ExchangeHeader/>
      <AccountBalance amount = {this.state.balance} showBalance  = {this.state.showBalance}
      handleBalanceVisibilityChange = {this.handleBalanceVisibilityChange}/> 
      <CoinList coinData ={this.state.coinData} handleRefresh = {this.handleRefresh}
      showBalance = {this.state.showBalance}/> 
    </ContainerAll>
    )
  }
}

export default App;

CoinList.jsx

import React, { Component } from 'react'
import Coin from '../Coin/Coin';
import styled from 'styled-components'

const Table = styled.table` 
    margin: 50px auto 50px auto;
    display: inline-block;
    font-size: 1.4rem;
    text-align: center;
    background-color: #000080;
    -webkit-box-shadow: 16px 17px 77px 75px rgba(0,0,0,0.8); 
    box-shadow: 16px 17px 77px 75px rgba(0,0,0,0.8)
`

export default class CoinList extends Component {
  
  render() {
      return (
        <div>
          <Table>
              <thead> 
                <tr>
                  <th>Name</th>
                  <th>Ticker</th>
                  <th>Price</th>
                  {this.props.showBalance ? <th>Balance</th> : null}
                  <th>Update</th>
                </tr>
              </thead>
            <tbody >
                { 
                this.props.coinData.map(({key,id, name, ticker, price, balance}) => <Coin key = {key} // changed to key= {key} 
                id = {id} // New i cannot use key 
                handleRefresh = {this.props.handleRefresh}
                name = {name} 
                ticker = {ticker} 
                price = {price} 
                balance = {balance}
                showBalance = {this.props.showBalance}/>) 
                }
            </tbody>  
          </Table> 
        </div>
        )
    }
}

Coin.jsx

import React, { Component } from 'react'
import PropTypes from 'prop-types';  

import styled from 'styled-components'
const Td = styled.td` 
    border: 1px solid black;
    width: 60vh;
`

export default class Coin extends Component {
    handleClick = (event) => {  
        event.preventDefault(); 
        this.props.handleRefresh(this.props.id); // pass the id 
    }
        
    render() {
        return ( 
            <tr>
                <Td>{this.props.name}</Td>
                <Td>{this.props.ticker}</Td>
                <Td>${this.props.price}</Td>
                {this.props.showBalance ? <Td>${this.props.balance}</Td> : null }
                
                <Td>
                    <form action = "#" method = "POST"/>  
                        <button onClick={this.handleClick }>Refresh</button>
                </Td>
            </tr>    
        );
    }
}

Component.propTypes = {
    name: PropTypes.string,
    ticker: PropTypes.string,
    price: PropTypes.number,
    balance: PropTypes.number,  
    id: PropTypes.string, 
};

2 Likes

I keep getting this error 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Anyone familiar with how fix this? I even copied Zsolt’s code and still kept getting this error.

handleRefresh = async (nKey) => {
    let priceOb = await axios.get('https://api.coinpaprika.com/v1/tickers/'+nKey);
    let newPrice = Number(parseFloat(Number(priceOb.data.quotes['USD'].price).toFixed(4)));
     const newCoinData = this.state.coinData.map(function(values){
        let newValue = {...values};
        console.log(values);
        console.log(newValue);
        if (nKey === values.key) {
          newValue.price = newPrice;
        }
       
        return newValue;
     });

     this.setState({ coinData: newCoinData});
    }

Added tickerId to Coin.

<Coin key={key} 
              handleRefresh={this.props.handleRefresh}
              name={name} 
              ticker={ticker} 
              price={price}
              balance ={this.props.visible ? balance : "*"} 
              tickerId = {key}/>

Github Link

Coin Exchange Homepage

I committed some old code in comments in App.js. It will be removed in a future commit.

    handleRefresh = async (valueChangeId) => {
    const tickerUrl = `https://api.coinpaprika.com/v1/tickers/${valueChangeId}`;
    const response = await axios.get(tickerUrl);
    const newPrice = formatPrice(response.data.quotes.USD.price);

    const newCoinData = this.state.coinData.map( function(values) {
      let newValues = { ...values };

      if(valueChangeId === values.ticker) {
        newValues.price = newPrice;
      }
      return newValues;
    });
    this.setState({coinData: newCoinData});
  }

when I hit refresh I get this error:

Access to XMLHttpRequest at 'https://api.coinpaprika.com/v1/tickers/ETH' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

@zsolt-nagy What does this mean? Is this an API access restriction of some sort?

So… It would be great to get a reply on here. I’m stuck on the handleRefresh update function. My code threw an error, so I tried using Zsolt’s code copied EXACTLY… Still throwing… Here’s my error:

Access to XMLHttpRequest at 'https://api.coinpaprika.com/v1/tickers/BTC' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

and the line below that error:

Uncaught (in promise) Error: Network Error
    at createError (createError.js:16)
    at XMLHttpRequest.handleError (xhr.js:84)

So how do I fix this?? Again, I’m using Zsolt’s EXACT code. This error didn’t come up in the course material video, but it did in my app.

ADMINS PLEASE ASSIST so that I can move forward in the course… Thank you!

Hi @jonsax,

Please share your github link so that I can download your app and debug to see if you have the right code in place especially with regards to setting http headers in your server.

Most of the time code snippets are not enough to debug application-level problems.

Waiting for your response.