Exercise - Refresh the Prices on Click

Finally bullish on React🤣
Solution:
App.js

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

const Div = styled.div`
  text-align: center;
  background-color: rgb(0, 65, 139);
  color: #cccccc;
`;

const COIN_COUNT = 10;
const formatPrice = price => parseFloat(Number(price).toFixed(4));

class App extends React.Component{
  state = {
    balance: 10000,
    showBalance: false,
    coinData: []
  };
      /*
      {
        name: "Bitcoin",
        ticker: "BTC",
        balance: 0.5,
        price: 9999.99
      },
      {
        name: "Ethereum",
        ticker: "ETH",
        balance: 32.0,
        price: 299.99
      },
      {
        name: "Tether",
        ticker: "USDT",
        balance: 0,
        price: 1.0
      },
      {
        name: "Ripple",
        ticker: "XRP",
        balance: 1000,
        price: 0.2
      },
      {
        name: "Bitcoin Cash",
        ticker: "BCH",
        balance: 0,
        price: 297.99
      },
      */
    
  componentDidMount = async () => {
   const response =  await axios.get('https://api.coinpaprika.com/v1/coins');
   const coinIds = response.data.slice(0, COIN_COUNT).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,
        name: coin.name,
        ticker: coin.symbol,
        balance: 0,
        price: formatPrice(coin.quotes.price),

    };
   });
    // Retrieve the prices
    this.setState({ coinData: coinPriceData });
  }
 
  handleBalanceVisibilityChange = () => {
        this.setState( function(oldState) {
          return {
            ...oldState,
            showBalance: !oldState.showBalance,
          }
        });
      }
      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.key ) {
          newValues.price = newPrice;
        }
        return newValues;
        });
        this.setState({ coinData: newCoinData});
      }
    render() {
    return (
        <Div className="App">
        <AppHeader />
        <AccountBalance 
          amount={this.state.balance} 
          showBalance={this.state.showBalance} 
          handleBalanceVisibilityChange={this.handleBalanceVisibilityChange}/>
        <CoinList 
        coinData={this.state.coinData} 
        showBalance={this.state.showBalance}
        handleRefresh={this.handleRefresh} />
          </Div> 
    );
  }

}
          
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;
`;

export default class CoinList extends Component {
    render() {
        return (
            <Table>
          <head>
            <tr>
                <th>Name</th>
                <th>Ticker</th>
                <th>Price</th>
                {this.props.showBalance ? <th>Balance</th> : null }
                <th>Actions</th>
                </tr>
            </head>
            <tbody>
                {
                  this.props.coinData.map( ({key, name, ticker, balance, price}) =>
                    <Coin key={key} 
                     handleRefresh={this.props.handleRefresh}
                     name={name} 
                     ticker={ticker} 
                     balance={balance}
                     showBalance={this.props.showBalance}
                     price={price}
                     tickerId={key} />
                    )
                  }
                </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 black; 
  width; 25vh; 
  `;

 export default class Coin extends Component {
  

 handleClick = (event) => {
   //Prevent the default action of submitting the form 
   event.preventDefault();
   
   this.props.handleRefresh(this.props.tickerId);
  }

       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>
                
            );
    }
}

Coin.propTypes = {
  name: PropTypes.string.isRequired,
  ticker: PropTypes.string.isRequired,
  price: PropTypes.number.isRequired,
}
1 Like

App.js - handleRefresh function

handleRefresh = (valueChangeTicker) => {
      console.log(valueChangeTicker);
      const newCoinData = this.state.coinData.map( function( values ) {
        let newValues = { ...values }; //shallow copy
        if ( valueChangeTicker === values.ticker) {
          /*const randomPercentage = 0.995 + Math.random() * 0.01;
          newValues.price *= randomPercentage;*/
            axios.get('https://api.coinpaprika.com/v1/tickers/'+values.key)
                  .then( coinResponse => {
                  const coin = coinResponse.data;
                  let newPrice = 0;
                   newPrice = parseFloat(Number(coin.quotes.USD.price).toFixed(2));
                   newValues.price = newPrice;
                   console.log(newValues.price);
                  });
        }
        return newValues;
      });
      console.log(newCoinData);
      this.setState({coinData: newCoinData});
    }
1 Like
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;
`;

export default class Coin extends Component {
 
  handleClick = (event) => {
    event.preventDefault();
    this.props.handleRefresh(this.props.tickerId);
  }

    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>
          );
    }
}

Coin.propTypes = {
  name: PropTypes.string.isRequired,
  ticker: PropTypes.string.isRequired,
  price: PropTypes.number.isRequired
}
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;
`;

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}) =>
              <Coin key = {key}
                    handleRefresh = {this.props.handleRefresh}
                    name = {name}
                    ticker = {ticker}
                    showBalance = {this.props.showBalance}
                    balance = {balance}
                    price = {price} 
                    tickerId = {key}/>
            )
          }
        </tbody>
      </Table>
    )
  }
}

App.js
const formatPrice = price => parseFloat(Number(price).toFixed(4));

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.key) {
        newValues.price = newPrice;
      }
      return newValues
    });
    this.setState({coinData: newCoinData});
  }
  render() {
    return (
      <Div>
        <AppHeader />
        <AccountBalance 
          amount={this.state.balance} 
          showBalance={this.state.showBalance} 
          handleBalanceVisibilityChange={this.handleBalanceVisibilityChange}/>
        <CoinList 
          coinData={this.state.coinData} 
          showBalance={this.state.showBalance}
          handleRefresh={this.handleRefresh}/>
      </Div>
    );
  }
1 Like

app.js

 handleRefresh = async (changedTickerValue) => {
    const priceData = await axios.get(coinTickerUrl + changedTickerValue)
    const newCoinData = this.state.coinData.map((values) => {
      let newValues = { ...values }
      if (changedTickerValue === values.ticker) {
        // instead of getting the price change statically, we'll get it from the API
        newValues.price = parseFloat(
          Number(priceData.data.quotes.USD.price).toFixed(4),
        )
      }
      return newValues
    })
    this.setState({ coinData: newCoinData })
  }

coinList:

<tbody>
                    {this.props.coinData.map(({ key, name, ticker, balance, price }) => (
                        <Coin
                            key={key}
                            id={key}
                            handleRefresh={this.props.handleRefresh}
                            name={name}
                            ticker={ticker}
                            price={price}
                            showBalance={this.props.showBalance}
                            balance={balance}
                        />
                    ))}
                </tbody>

coin

handleClick = (e) => {
        e.preventDefault()
        this.props.handleRefresh(this.props.id)
}

...

<Td>
    <form action="#" method="POST">
        <Button onClick={this.handleClick}>Refresh</Button>
    </form>
</Td>
1 Like

This is my solution guys!!

  handleRefresh = async (valueChangeTicker) => {
    const newCoinData = await Promise.all(this.state.coinData.map(async (values) => {
      let newValues = {...values};
      if(valueChangeTicker === values.ticker) {
        //refresh the coin
        const refreshInfo = await axios.get(`https://api.coinpaprika.com/v1/tickers/${values.key}`);
        newValues.price = parseFloat(refreshInfo.data.quotes.USD.price.toFixed(4));
      }
      return newValues;
    }));
      console.log(newCoinData)
      this.setState({ coinData: newCoinData });
  }
1 Like
  handleRefresh = async (changedTicker) => {
    const response = await axios.get(tickerUrl + changedTicker)

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

        const newPrice = response.data.quotes.USD.price
        newValues.price = parseFloat(newPrice.toFixed(5))

      }
      return newValues
    })

    this.setState({ coinData: newCoinData })
  }
1 Like

@Malik Hello Malik,I am not sure where post this question but I keep getting this error. Everything works but it’s annoying seeing this error. Do you know what this is about?

Error handling response: TypeError: Cannot read properties of undefined (reading 'takeRecords')
    at Function.e.closeListeners (chrome-extension://clmkdohmabikagpnhjmgacbclihgmdje/content-script.js:1:5858)
    at chrome-extensi

I got stuck for a while because I couldn’t get the Coin component to see the prop “key” - still don’t really understand why. But when I pass it a different prop from the CoinList, in this case id={key}, it seems to work. Then, just pass the id prop back up from the Coin component and change the handleRefresh in App.js function like so:

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

Having changed the handleRefresh event in the App.js file, basically changed the newprice value to a parsed fixed digit number and brought in the API as a promise to the event. Everything else remained the same. :relaxed:

App.js
handleRefresh = async (valueChangeKey) => {
    const tickerUrl = 'https://api.coinpaprika.com/v1/tickers/';
    const newValue =  await axios.get( tickerUrl + valueChangeKey);
    const responses = this.state.coinData.map(function(values) {
      let newValues = { ...values };
      if (valueChangeKey === values.key) {
        newValues.price = parseFloat(Number(newValue.data.quotes['USD'].price).toFixed(4));
      }
      return newValues;
    });
    this.setState({ coinData: responses });

Sharing my implementation before watching the next video for the solution:

In App.js

...
const COIN_DTL = 'https://api.coinpaprika.com/v1/tickers/';
...
  handleRefresh = async (keyUpdateValue) => {

    const coinUpdatedResult = await axios.get(COIN_DTL + keyUpdateValue);
    const newCoinData = this.state.coinData.map( (coinValues) =>
      {
        let newPrice = coinValues.price;
        if (coinValues.key === keyUpdateValue) {
          newPrice = coinUpdatedResult.data.quotes['USD'].price;
        }
...

Add an ‘id’ prop in CoinList.jsx

...
            this.props.coinData.map(
                ({key, name, ticker, balance, price}) => 
                <Coin key={key} id={key} name={name} ticker={ticker} balance={balance} price={price} handleRefresh={this.props.handleRefresh} showBalance={this.props.showBalance} />
            )
...

Changing the prop to ‘id’ in the event handler instead of the ‘ticker’ in Coin.jsx

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

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

CORS ERROR: Need Help!
I have a cross-origin resource sharing error. I have tried a few things, and when I use the cross-origin unblocker extension for chrome, it gets rid of cors message and says 404 for the coins that it is retrieving. Please help! Thanks!

 componentDidMount = async () => {
      const response = await axios.get(`https://api.coinpaprika.com/v1/coins`);
      const coinIds = response.data.slice(0, COIN_COUNT).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(function(response) {
        const coin = response.data;
        return {
          key: coin.id,
          name: coin.name,
          ticker: coin.symbol,
          balance: 0,
          price: coin.quotes.USD.price,
        };
      })
      this.setState({ coinData: coinPriceData });
  };

I try using cors unblocker extension from chrome, but then it returns 404. Please help! Thanks!

1 Like
import React from 'react';
import CoinList from './components/CoinList/CoinList';
import AccountBalance from './components/AccountBalance/AccountBalance';
import CoinExchangeHeader from './components/CoinExchangeHeader/CoinExchangeHeader';
import styled from 'styled-components';
import axios from 'axios'

const Div = styled.div `
  text-align: center;
  background-color: #282c34;
  color: white;
  `;

const COIN_COUNT = 10;
const formatPrice = price => parseFloat(Number(price).toFixed(4))

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

    {
      name: 'Bitcoin',
      ticker: 'BTC',
      balance: 0.5,
      price: 1000000.00
    },
    {
      name: 'Etherium',
      ticker: 'ETH',
      balance: 100,
      price: 180000.00
    },
    {
      name: 'Tether',
      ticker: 'USDT',
      balance: 0.00,
      price: 1.00
    },
    {
      name: 'Binance Coin',
      ticker: 'BNB',
      balance: 87.03,
      price: 14300.02
    },
    {
      name: 'Ripple',
      ticker: 'XRP',
      balance: 1000,
      price: 15.86
    }
    */
  ]
  }
  componentDidMount = async () => {
  const response = await axios.get('https://api.coinpaprika.com/v1/coins')
  const coinIds = response.data.slice(0, COIN_COUNT).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(function (response) {
      const coin = response.data;
      return {
        key: coin.id,
        name: coin.name,
        ticker: coin.symbol,
        balance: 0,
        price: formatPrice(coin.quotes['USD'].price),
      };
  })
  this.setState({ coinData: coinPriceData });
}
  handleBalance = () => {
    this.setState(function (oldState) {
      return {
        ...oldState,
        showBalance: !oldState.showBalance
      }
    });
}
  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.key) {
    
          newValues.price = newPrice;
        }
        return newValues;
      });
      this.setState({ coinData: newCoinData })
    };
  render() {
    return (
      <Div className="App">
        <CoinExchangeHeader/>
        <AccountBalance
          amount={this.state.balance}
          showBalance={this.state.showBalance}
          handleBalance={this.handleBalance} 
        />
        <CoinList
          coinData={this.state.coinData}
          handleRefresh={this.handleRefresh}
          showBalance={this.state.showBalance} 
        />
      </Div>
    );
  } 
}

export default App;

hey did you ever get this solved if not i can try help for you

App.js
  handleRefresh = async (tickerId) => {
    const response = await axios.get(
      `https://api.coinpaprika.com/v1/tickers/${tickerId}`
    );

    const newCoinData = this.state.coinData.map((values) => {
      let newValues = { ...values };
      if (tickerId === values.key) {
        newValues.price = parseFloat(
          Number(response.data.quotes.USD.price).toFixed(9)
        );
      }
      return newValues;
    });

    this.setState({ coinData: newCoinData });
  };
CoinList.js
export default class CoinList extends Component {
  render() {
    return (
      <Table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Ticker</th>
            <th>Price</th>
            <th>Balance</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          {this.props.coinData.map(({ key, name, ticker, price, balance }) => (
            <Coin
              key={key} 
              id={key} // use id for handle
              handleRefresh={this.props.handleRefresh}
              name={name}
              ticker={ticker}
              showBalance={this.props.showBalance}
              balance={balance}
              price={price}
            />
          ))}
        </tbody>
      </Table>
    );
  }
}
Coin.js
  handleClick = (event) => {
    event.preventDefault(); // prevent default action post and refresh page
    this.props.handleRefresh(this.props.id); // use id not key
  };
1 Like
App
import React, { Component } from 'react'
import AccountBalance from './components/AccountBalance'
import CoinList from './components/CoinList';
import Header from './components/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

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

  componentDidMount = async () => {
    const response = await axios.get('https://api.coinpaprika.com/v1/coins')
    const coinIds = response.data.slice(0, COIN_COUNT).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(coin => {
      return {
        key: coin.data.id,
        name: coin.data.name,
        ticker: coin.data.symbol,
        balance: 0,
        price: parseFloat(Number(coin.data.quotes.USD.price).toFixed(4))
      }
    })
    this.setState({ coinData: coinPriceData })
  }

  handleRefresh = async (valueChangeKey) => {
    const url = 'https://api.coinpaprika.com/v1/tickers/' + valueChangeKey
    const response = await axios.get(url)
    const newPrice = parseFloat(Number(response.data.quotes.USD.price).toFixed(4))
    const newCoinData = this.state.coinData.map(( values ) => {
      let newValues = {...values}
      if(valueChangeKey === values.key){
        newValues.price = newPrice
      }
      return newValues
    })
    this.setState({ coinData: newCoinData })
  }

  handleBalanceVisability = () => {
    this.state.showBalance === true ? this.setState({ showBalance: false }) : this.setState({ showBalance: true })
  }

  render(){
    return (
      <Div className="App">
        <Header />
        <AccountBalance amount={this.state.balance} showBalance={this.state.showBalance} handleBalanceVisability={this.handleBalanceVisability}/>
        <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'
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() {
    return (
        <Table className='coin-table'>
        <thead>
          <tr>
            <th>Name</th>
            <th>Ticker</th>
            <th>Price</th>
            {this.props.showBalance && <th>Balance</th>}
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          {
          this.props.coinData.map(({ key, name, ticker, price, balance })=> 
          <Coin 
          balance={balance} 
          showBalance={this.props.showBalance} 
          handleBalanceVisability={this.props.handleBalanceVisability}
          handleRefresh={ this.props.handleRefresh } 
          key={key} 
          id={key}
          name={name} 
          ticker={ticker} 
          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) => {
        event.preventDefault()
        this.props.handleRefresh( this.props.id )
    }

    render() {
        return (
            <tr className='coin-row'>
                <Td>{ this.props.name }</Td>
                <Td>{ this.props.ticker }</Td>
                <Td>${ this.props.price }</Td>
                {this.props.showBalance && <Td> { this.props.balance }</Td>}
                <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
handleCoinRefresh = async (ticker) => {
    const found = this.state.coinData.find(
      (element) => element.ticker === ticker
    );
    const freshCoinDataPrice = await axios.get(
      `https://api.coinpaprika.com/v1/tickers/${found.key}`
    );
    const newPrice = freshCoinDataPrice.data.quotes.USD.price;
    console.log(newPrice);
    let newCoinData = this.state.coinData.map(function (coin) {
      let newCoin = coin;
      if (ticker === coin.ticker) {
        const randomPercentage = 0.994 + Math.random() * 0.01;
        newCoin.price = Number(newPrice.toFixed(4));
      }
      return newCoin;
    });
    this.setState({ coinData: newCoinData });
  };
1 Like
handleRefresh = (valueChangeKey) => {
    const newCoinData =  this.state.coinData.map( function(values) {
      let newValues = {...values};  // * Shallow clone of the original object to avoid pointer issue. 
      if ( valueChangeKey === newValues.ticker) {
        console.log("Key is", newValues.key);
        const response = axios.get('https://api.coinpaprika.com/v1/tickers/' + newValues.key);
        response.then(function(response) {
          const coin = response.data;
          newValues.price = coin.quotes.USD.price;
          console.log("Price is ", newValues.price);
        }).catch(function(error) {
          console.log(error);
        });
      }
      return newValues;
    });
    this.setState({coinData: newCoinData});
  }
1 Like

Second Version

 handleRefresh = async (valueChangeId) => {
    console.log(valueChangeId);
    const tickerURL = 'https://api.coinpaprika.com/v1/tickers/';
    const response = await axios.get(tickerURL + valueChangeId);
    const newCoinData = this.state.coinData.map( function(coin) {
      if (valueChangeId === coin.id) {
        console.log("Price of the", coin.name, "is", response.data.quotes.USD.price);
        return {
          key: coin.key,
          name: coin.name,
          ticker: coin.ticker,
          id: coin.id,
          balance: coin.balance,
          price: response.data.quotes.USD.price,
        }
      }
      return coin;
    });
    this.setState({ coinData: newCoinData });
  }
1 Like

There goes my solution:

	handleRefresh = (symbol) => {
		axios.get(`https://api.coinpaprika.com/v1/tickers`).then((res) => {
			let coinDataUpdatedPrices = this.state.coinData.map((coin) => {
				let newPrice = coin.price
				if (coin.symbol === symbol) {
					for (let ticker of res.data) {
						if (ticker.id === coin.key) {
							newPrice = ticker.quotes.USD.price
						}
					}
				}
				return {
					...coin,
					price: newPrice,
				}
			})
			return coinDataUpdatedPrices
		})
		.then((info) => this.setState({ coinData: info }))
	}
1 Like

Hellow :slight_smile:

I modified the code so that the main balance table contains the top 15 coins.

Clicking on Refresh button refreshes the price (not very spectacular because coinpaprika does not seem to update the price too often)

The new handleRefresh() function is here:

Apps.js code
import AccountBalance from './Components/AccountBalance/AccountBalance';
import React from 'react';
import AppHeader from './Components/AppHeader/AppHeader';
import CoinList from './Components/CoinList/CoinList';
import styled from 'styled-components';
import axios from 'axios';


const AppStyle = styled.div`
text-align: center;
`;


const COINT_COUNT = 15;


class App extends React.Component {

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


  componentDidMount = async ()=>{ 

    try{

      const response = await axios.get('https://api.coinpaprika.com/v1/tickers');
      const topCoins = response.data.slice(0, COINT_COUNT).map( coin => coin.id); // Get the top 5 coins
      const tickerurl = "https://api.coinpaprika.com/v1/tickers/";

      const promises = topCoins.map( async (coin) => { return axios.get(tickerurl + coin); });
      const responses = await Promise.all(promises);

      const newCoinData = responses.map( response =>
        {
          const coin = response.data;
          return{
            id: coin.id,
            name: coin.name,
            ticker: coin.symbol,
            price: coin.quotes.USD.price,
            balance: 0
          };
        }
      );


      this.setState({ coinData: newCoinData});

    }
    catch(error){
      console.log(error);
    }

  }


  handleRefresh = async(id)=> {

    console.log('handleRefresh', id);

    async function getNewPrice(id){
      const tickerurl = `https://api.coinpaprika.com/v1/tickers/${id}`;

      try{
        const response = await axios.get(tickerurl);
        const coin = response.data;
        return coin.quotes.USD.price;
      }
      catch(error){
        console.log(error);
      }

    }

    const newCoinDataPromises = this.state.coinData.map( async (values)=> { 

      const newValues = { ...values};

      if(id === values.id){

        const newPrice = await getNewPrice(id);
        console.log("newPrice", newPrice);

        newValues.price = newPrice;

      }
      return newValues;
      
    })

    const newCoinData = await Promise.all(newCoinDataPromises);

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


  handleHideBalance = ()=>{

    this.showBalance = !this.showBalance;

    this.setState({showBalance: this.showBalance});
  }

  render() {
    return (
      <AppStyle>
        <AppHeader />
        <h2>Today's Cryptocurrency Prices by Market Cap</h2>
        <AccountBalance showBalance={this.showBalance} amount={this.state.balance}  handleHideBalance={this.handleHideBalance}/>
        <CoinList showBalance={this.showBalance} coinData={this.state.coinData} handleRefresh={this.handleRefresh}/>
      </AppStyle>
    );
  }

}

export default App;


Had to pass down the coin id down to the Coin component, both as an “id” prop and as a “key”

CoinList.js

import React from 'react';
import Coin from '../Coin/Coin';
import styled from 'styled-components';



const CoinTable = styled.table`
margin: 50px auto 50px auto;
text-align: left;
`;




export default class CoinList extends React.Component{

    render() {

        return(
        <CoinTable>
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Ticker</th>
                    <th>Price</th>
                    <th>Balance</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>

                {
                    // console.log(this.props.coinData);

                    this.props.coinData.map( ({id, name, ticker, price, balance} ) => 
                        <Coin 
                        key={id}
                        id={id}
                        name={name}
                        price={price}
                        ticker={ticker}
                        balance={balance}
                        showBalance={this.props.showBalance}
                        handleRefresh={this.props.handleRefresh}
                        />
                    )
                }

            </tbody>
        </CoinTable>
        );
    }

}



 

Github:
https://github.com/CodingInLondon/moralisacademy-react/tree/179821c1d25fc8b6ceb464adc9431c5aef5f583d/coin-exchange/src

1 Like