Hide the Balance exercise

That was a lot to learn and still there is more. Safe to say, my app is working as it should, but if any other suggestions/recommendations can be given, I’m all ears :+1:

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

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

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      balance: 10000,
      showBalance: true,
      coinData: [
        {
          name: 'Bitcoin',
          ticker: 'BTC',
          balance: 0.5,
          price: 42050.77
        },
        {
          name: 'Ethereum',
          ticker: 'ETH',
          balance: 32,
          price: 3129.90
        },
        {
          name: 'Tether',
          ticker: 'USDT',
          balance: 15000,
          price: 1.0
        },
        {
          name: 'Solana',
          ticker: 'SOL',
          balance: 50,
          price: 121.50
        },
        {
          name: 'Crypto.com',
          ticker: 'CRO',
          balance: 359801,
          price: 0.34
        }
      ]
    }
    this.handleRefresh = this.handleRefresh.bind(this);
    this.handleShowBalance = this.handleShowBalance.bind(this);
  }
  handleRefresh(valueChangeTicker) {
    const newCoinData = this.state.coinData.map(function( {ticker, name, price} ) {
      let newPrice = price;
      if (valueChangeTicker === ticker) {
        const randomPercentage = 0.995 + Math.random() * 0.01;
        newPrice = newPrice * randomPercentage;
      }
      return {
        ticker,
        name,
        price: newPrice
      }
    });
    this.setState({ coinData: newCoinData });
  }
  handleShowBalance() {
    this.setState({ showBalance: !this.state.showBalance });
  }
  render() {
    return (
      <Div>
        <TitleList />
        <AccountBalance amount={this.state.balance} 
                        showBalance={this.state.showBalance} 
                        handleShowBalance={this.handleShowBalance} />
        <CoinList coinData={this.state.coinData} 
                  handleRefresh={this.handleRefresh}
                  showBalance={this.state.showBalance} />
      </Div>
    );
  }
}
  

export default App;
CoinList.js
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>
                        <th>Balance</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                {
                    this.props.coinData.map( ({name, ticker, balance, price}) => 
                    <Coin key={ticker} 
                          handleRefresh={this.props.handleRefresh} 
                          name={name} 
                          ticker={ticker}
                          balance={balance}
                          showBalance={this.props.showBalance} 
                          price={price} />
                    )
                }
                </tbody>
            </Table>
        )
    }
}
Coin.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

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

export default class Coin extends Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }
    
    handleClick(event) {
        //prevent the default action of submitting the form
        event.preventDefault();
        this.props.handleRefresh(this.props.ticker);
    }

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

Coin.propTypes = {
    name: PropTypes.string.isRequired,
    ticker: PropTypes.string.isRequired,
    price: PropTypes.number.isRequired,
    balance: PropTypes.number.isRequired
}
AccountBalance.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const Section = styled.section`
    font-size: 2rem;
    text-align: left;
    padding: 1.5rem 0 1.5rem 5rem;
    color: aliceblue;
`;

const Button = styled.button`
    font-size: 1.3rem;
    margin: 1.5rem 0 1.5rem 5rem;
    background-color: light-gray;
    border: 1px solid black;
    border-radius: 5px; 
`;


export default class AccountBalance extends Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick(event) {
        event.preventDefault();
        this.props.handleShowBalance();
    }

    render() {
        const buttonText = this.props.showBalance ? "Hide Balance" : "Show Balance";
        const balance = this.props.showBalance ? <span><strong>Balance:</strong> ${ this.props.amount }</span> : "*****";
        return (
            <Section>
               { balance }
               <Button onClick={this.handleClick}>{ buttonText }</Button>
            </Section>
        );
    }
}


AccountBalance.propTypes = {
    amount: PropTypes.number.isRequired
}

had to look up in next video for a solution, but I managed to solve problem with refresh button :sweat_smile:

app

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'

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


class App extends React.Component {

  constructor(props) {
    super(props);
    this.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
        }
      ]
    }
    this.handleRefresh = this.handleRefresh.bind(this);
    this.handleBalance = this.handleBalance.bind(this);
  }

  handleBalance() {
    this.setState(function (oldState) {
      return {
        ...oldState,
        showBalance: !oldState.showBalance
      }
    });
}
 
handleRefresh(valueChangeTicker) {
  const newCoinData = this.state.coinData.map(function ({ ticker, name, price, balance }) {
    let newPrice = price;
    if (valueChangeTicker === ticker) {
      const randomPercentage = 0.995 + Math.random() * 0.01;
      newPrice = newPrice * randomPercentage;
    }
    return {
      ticker,
      name,
      price: newPrice,
      balance
    }
  });

    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;

account balance

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

const Section = styled.section`
font-size: 2rem;
padding: 2rem;
`;

export default class AccountBalance extends Component {

    render() {
        const buttonText = this.props.showBalance ? 'Hide Balance' : 'Show Balance';
        let content = null;
        if (this.props.showBalance) {
            content = <> Balance: ${this.props.amount} </>;
        }
      return ( 
          <Section>
            {content} 
            <button onClick={this.props.handleBalance}>{buttonText}</button>
          </Section>
      )
  }
}

AccountBalance.propTypes = {
    amount: PropTypes.number.isRequired
}

coinlist

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

const Table = styled.table`
  background-color: #282c34;
  min-height: 20vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  color: white;
  `;

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

export default class Coin extends Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }


    handleClick(event) {
        event.preventDefault();
        this.props.handleRefresh(this.props.ticker);
    }

  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="#" 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,
    balance: PropTypes.number.isRequired
}
App.jsx

class App extends React.Component {
constructor(props){
super(props);
this.state = {
balance: 10000,
showBalance: true,
coinData: […]
}
this.handleRefresh = this.handleRefresh.bind(this);
this.handleBalanceShow = this.handleBalanceShow.bind(this);
}

handleBalanceShow(){
this.setState({showBalance: !this.state.showBalance});
}

handleRefresh(changedTicker) {
const newCoinData = this.state.coinData.map(function({ticker, name, price, balance}){
let newPrice = price;
if(changedTicker === ticker){
const randomPercentage = 0.995 + Math.random() * 0.1;
newPrice = newPrice * randomPercentage;
}

  return {
    ticker,
    name,
    price: newPrice,
    balance
  }

});

this.setState({ coinData: newCoinData});

}

render(){

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

}
}

AccountBalance.jsx

render() {

const buttonText = this.props.showBalance? 'Hide Balance': 'Show Balance';

let content = null;

 if( this.props.showBalance ){

    content = <>Balance:$ {this.props.amount}</>;

 }

 return (

  <Section>        

    {content}

    <button onClick={this.props.handleBalanceShow}>{buttonText}</button>

  </Section>

);

}

}

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(({name, ticker, price, balance})=>

            <Coin key={ticker}

                handleRefresh={this.props.handleRefresh}

                name={name}

                ticker={ticker}

                showBalance={this.props.showBalance}

                balance={balance}

                price={price} />

            )

        }
    </Table>

);

}

}

Coin.jsx

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>

 

);

}

}

1 Like

Man that was a lesson learnt, took longer than I thought, I had to watch the solution.
In the end the app works and I know how it function :slight_smile:

Here is my full code:

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

const Div = styled.div`
  text-align: center;
  background-color: rgb(33, 63, 109);
  color: white;
`;

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      balance: 10000,
      showBalance: true, // set showBalance state to true
      coinData: [
        {
          name: "Bitcoin",
          ticker: "BTC",
          balance: 3442.0,
          price: 9999.99,
        },
        {
          name: "Ethereum",
          ticker: "ETH",
          balance: 392.0,
          price: 1545.99,
        },
        {
          name: "IOTA",
          ticker: "MIOTA",
          balance: 32.0,
          price: 23.99,
        },
        {
          name: "Ripple",
          ticker: "XRP",
          balance: 392.0,
          price: 1.99,
        },
      ],
    };
    this.handleRefresh = this.handleRefresh.bind(this);
    this.handleBalance = this.handleBalance.bind(this); // add binding for handleBalance
  }

  // hide balance of account method for AccountBalance Component
  handleBalance() {
    this.setState(function (oldState) {
      return {
        ...oldState,
        showBalance: !oldState.showBalance,
      };
    });
  }

  handleRefresh(valueChangeTicker) {
    const newCoinData = this.state.coinData.map(function ({
      ticker,
      name,
      price,
    }) {
      // get old price value
      let newPrice = price;

      if (valueChangeTicker === ticker) {
        const randomPercentage = 0.995 + Math.random() * 0.01;
        newPrice = newPrice * randomPercentage;
      }

      return {
        ticker,
        name,
        price: newPrice,
      };
    });

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

  render() {
    return (
      <Div>
        <ExchangeHeader />
        <AccountBalance
          amount={this.state.balance}
          showBalance={this.state.showBalance} // pass down showBalance state to AccountBalance
          handleBalance={this.handleBalance} // pass in handleBalance method here
        />
        <CoinList
          coinData={this.state.coinData}
          handleRefresh={this.handleRefresh}
          showBalance={this.state.showBalance} // pass down showBalance state to CoinList
        />
      </Div>
    );
  }
}
CoinList.js
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>
            <th>Balance</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          {this.props.coinData.map(({ name, ticker, price, balance }) => (
            <Coin
              key={ticker}
              handleRefresh={this.props.handleRefresh}
              name={name}
              ticker={ticker}
              showBalance={this.props.showBalance} // pass down showBalance state to Coin component
              balance={balance}
              price={price}
            />
          ))}
        </tbody>
      </Table>
    );
  }
}

Coin.js
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 {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(event) {
    event.preventDefault(); // prevent default action post and refresh page
    this.props.handleRefresh(this.props.ticker);
  }

  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> // conditional statement show/hide balance
        ) : (
          <Td>$******</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,
};

AccountBalance.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";

const Section = styled.section`
  font-size: 2rem;
  text-align: left;
  padding: 1.5rem 0 1.5rem 5rem;
`;

const Button = styled.button`
  font-size: 1.4rem;
  margin: 1.5rem 0 1.5rem 5rem;
`;

export default class AccountBalance extends Component {
  render() {
    const buttonText = this.props.showBalance ? "Hide Balance" : "Show Balance";
    let balance = "*****";

    if (this.props.showBalance) {
      balance = <React.Fragment>{this.props.amount}</React.Fragment>;
    }

    return (
      <Section>
        Balance: ${balance}
        <Button onClick={this.props.handleBalance}>{buttonText}</Button>
      </Section>
    );
  }
}

AccountBalance.propTypes = {
  amount: PropTypes.number.isRequired,
};

2 Likes

i wouldnt worry this is normal. react is hard when its your first time because of its different syntax etc…but i gaurantee you in a month youll be wondering why you ever even botgered using vanilla js in the first place

1 Like

Hello
My ‘Hide Balance’ button is not working, here is my code:
App.js:

import React from 'react';
import AccountBalance from './components/AccountBalance/AccountBalance.jsx';
import CoinList from './components/CoinList/CoinList';
import styled from 'styled-components';
import Header from './components/Header/Header';

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

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      balance: 10000,
      showBalance: true,
      coinData: [
        {
          name: 'Bitcoin',
          ticker: 'BTC',
          balance: 0.5,
          price: 9999.99
        },
        {
          name: 'Ethereum',
          ticker: 'ETH',
          balance: 32,
          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: 298.99,
        }
      ]
    }
    this.handleRefresh = this.handleRefresh.bind(this);
    this.handleBalanceVisibilityChange = this.handleBalanceVisibilityChange.bind(this);
  } 
  handleBalanceVisibilityChange() {
    this.setState( function(oldState) {
      return {
        ...oldState,
        showBalance: !oldState.showBalance
      }
    });
  }

  handleRefresh(valueChangeTicker){
    const newCoinData = this.state.coinData.map( function( {ticker, name, price, balance} )  {
      let newPrice = price;
      if ( valueChangeTicker === ticker) {
        const randomPercentage = 0.995 + Math.random() * 0.01;
        newPrice = newPrice * randomPercentage;
      }
      return {
        ticker,
        name,
        balance,
        price: newPrice
      }

    }); 
    
   this.setState({ coinData: newCoinData });
  }
  render() {
    return (
      <Div className="App">
        <Header />
        <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;

AccountBalance.jsx:

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

const Section = styled.section`
    border: 1px solid red;
    font-size: 2rem;
    text-align: left;
    padding: 1.5rem 0 1.5rem 5rem;
`;

export default class AccountBalance extends Component {
  render() {
    const buttonText = this.props.showBalance ? 'Hide Balance' : 'Show Balance'
    let content = null;
    if (this.props.showBalance) {
        content = <>Balance: ${this.props.amount}</>;
    }
    return (
      <Section>
        {content}
        <button>{buttonText}</button>
      </Section>
    );
  }
}

AccountBalance.propTypes = {
    amount: PropTypes.number.isRequired
}

CoinList.jsx:

import React, { Component } from 'react'
import Coin from '../Coin/Coin.jsx';
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( ({name, ticker, price, balance}) =>
            <Coin key={ticker}
                  handleRefresh={this.props.handleRefresh}
                  name={name}
                  ticker={ticker}
                  showBalance={this.props.showBalance}
                  balance={balance}
                  price={price} /> 
            // ..value = name={name}, ticker={ticker}, price={price}
            )
          }
        </tbody>
      </Table>
    )
  }
}

Coin.jsx:

import React, { Component } from 'react'
//import "./Coin.css";
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { toHaveAccessibleDescription } from '@testing-library/jest-dom/dist/matchers';


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

export default class Coin extends Component {
  constructor(props){
      super(props);
      this.handleClick = this.handleClick.bind(this);
      
  }


  

  handleClick(event) {
        event.preventDefault();
        this.props.handleRefresh(this.props.ticker);
        
    
  }
  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.protoTypes = {
    name: PropTypes.string.isRequired,
    ticker: PropTypes.string.isRequired,
    price: PropTypes.number.isRequired
}
1 Like

taking a look now for you

1 Like

you dont have an onClick handler on your hideBalance button. change it to

`return (
      <Section>
        {content}
        <button onClick={this.props.handleVisibilityChange}>{buttonText}</button>
      </Section>`
)

this will change the states. you shoudl also try console.logging things to try debug where your going wrong

let me know if it works

1 Like

Hello
It still doesn’t work

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'

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


class App extends Component {
  constructor(props){
    super(props)
    this.state = {
      showBalance: true,
      balance: 10000,
      coinData: [
        {
          name: 'Bitcoin',
          ticker: 'BTC',
          balance: 0.5,
          price: 9999.99
        },
        {
          name: 'Ethereum',
          ticker: 'ETH',
          balance: 32,
          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: 298.99
        }
      ]
    }
    this.handleRefresh = this.handleRefresh.bind(this)
    this.handleBalance = this.handleBalance.bind(this)
  }
  
  handleRefresh (valueChangeTicker) {
    const newCoinData = this.state.coinData.map(({ ticker, name, price }) => {
      let newPrice = price
      if(valueChangeTicker === ticker){
        const randomPercentage = 0.995 + Math.random() * 0.01
        newPrice = newPrice * randomPercentage
     
      }
      return {
        ticker,
        name,
        price: newPrice
      }
    })
    this.setState({ coinData: newCoinData })
  }

  handleBalance(){
    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} handleBalance={this.handleBalance}/>
        <CoinList coinData={this.state.coinData} handleRefresh={this.handleRefresh} showBalance={this.state.showBalance}/>
      </Div>
    );
  }
}

export default App;

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 {
    constructor(props){
        super(props)
        this.handleClick = this.handleClick.bind(this)
    }

    handleClick(event) {
        event.preventDefault()
        this.props.handleRefresh(this.props.ticker)
    }

    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
}



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

AccountBalance
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'

const Section = styled.section`
  font-size: 2rem;
  text-align: left;
  padding: 1.5rem 0 1.5rem 5rem;
`;

export default class AccountBalance extends Component {
  constructor(props){
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick(event) {
    event.preventDefault()
    this.props.handleBalance()
  }

  render() {
    const buttonText = this.props.showBalance ? "Hide Balance" : "Show Balance"
    return (
        <Section>
          {this.props.showBalance && `Balance: $ ${ this.props.amount }`}
          <button onClick={ this.handleClick }>{ buttonText }</button>
        </Section>
    )
  }
}

AccountBalance.propTypes = {
    amount: PropTypes.number.isRequired
}
1 Like

hey can u DM me well get this solved tomorrow

App.js
import React from "react";
import "./App.css";
import AccountBalance from "./components/AccountBalance/AccountBalance";
import CoinsList from "./components/CoinsList/CoinsList";
import Header from "./components/Header/Header";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      balance: 10000,
      showBalance: true,
      coinData: [
        {
          name: "Bitcoin",
          ticker: "BTC",
          price: 30000,
          balance: 1,
        },
        {
          name: "Tether",
          ticker: "USDC",
          price: 1,
          balance: 10000,
        },
        {
          name: "Ethereum",
          ticker: "ETH",
          price: 2000,
          balance: 1,
        },
        {
          name: "Ripple",
          ticker: "XRP",
          price: 0.4,
          balance: 10,
        },
        {
          name: "Binance Coin",
          ticker: "BNB",
          price: 300,
          balance: 10,
        },
      ],
    };
    this.handleCoinRefresh = this.handleCoinRefresh.bind(this);
    this.toggleBalance = this.toggleBalance.bind(this);
  }

  toggleBalance() {
    this.setState({ showBalance: !this.state.showBalance });
  }

  handleCoinRefresh(ticker) {
    const found = this.state.coinData.find(
      (element) => element.ticker === ticker
    );
    let newCoinData = this.state.coinData.map(function ({
      name,
      ticker,
      price,
    }) {
      let newPrice = price;
      if (found.ticker === ticker) {
        const randomPercentage = 0.994 + Math.random() * 0.01;

        newPrice = newPrice * randomPercentage;
      }
      return {
        name,
        ticker,
        price: newPrice,
      };
    });
    this.setState({ coinData: newCoinData });
  }
  render() {
    return (
      <div className="App">
        <Header />
        <AccountBalance
          amount={this.state.balance}
          toggleBalance={this.toggleBalance}
          showBalance={this.state.showBalance}
        />
        <CoinsList
          coins={this.state.coinData}
          handleCoinRefresh={this.handleCoinRefresh}
          showBalance={this.state.showBalance}
        />
      </div>
    );
  }
}

export default App;
AccountDetails.jsx

import PropTypes from “prop-types”;

import React, { Component } from “react”;

import styled from “styled-components”;

const Section = styled.section`

color: white;

font-size: 2rem;

text-align: left;

padding: 1.5rem 0 1.5rem 5rem;

`;

export default class AccountBalance extends Component {

constructor(props) {

super(props);

this.toggleBalance = this.toggleBalance.bind(this);

}

toggleBalance() {

this.props.toggleBalance();

}

render() {

const buttonText = this.props.showBalance ? "Hide balance" : "Show balance";

const balance = this.props.showBalance ? this.props.amount : "*****";

return (

  <Section>

    Balance: ${balance}

    <button onClick={this.toggleBalance}>{buttonText}</button>

  </Section>

);

}

}

AccountBalance.propTypes = {

amount: PropTypes.number.isRequired,

};

CoinsList.jsx

import React, { Component } from “react”;

import Coin from “…/Coins/Coins”;

export default class CoinsList extends Component {

render() {

return (

  <table className="coin-prices">

    <thead>

      <tr>

        <th>Name</th>

        <th>Ticker</th>

        <th>Price</th>

      </tr>

    </thead>

    <tbody>

      {this.props.coins.map(({ name, ticker, price, balance }) => {

        const balanceToggled = this.props.showBalance ? balance : "*****";

        return (

          <Coin

            key={ticker}

            name={name}

            ticker={ticker}

            price={price}

            balance={balanceToggled}

            handleCoinRefresh={this.props.handleCoinRefresh}

          />

        );

      })}

    </tbody>

  </table>

);

}

}

Coins.jsx
import React, { Component } from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
const TD = styled.td`
  border: 1px solid white;
  width: 25vh;
`;

export default class Coins extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(event) {
    event.preventDefault();
    console.log("refresh pressed");
    this.props.handleCoinRefresh(this.props.ticker);
  }
  render() {
    return (
      <tr>
        <TD>{this.props.name}</TD>
        <TD>{this.props.ticker}</TD>
        <TD>${this.props.price}</TD>
        <TD>
          <form action="#" method="GET">
            <button onClick={this.handleClick}>Refresh</button>
          </form>
        </TD>
        <TD>${this.props.balance}</TD>
      </tr>
    );
  }
}
Coins.propTypes = {
  name: PropTypes.string.isRequired,
  ticker: PropTypes.string.isRequired,
  price: PropTypes.number.isRequired,
};

1 Like

1 Like

very nice looking project man. super impressive keep it up. excited to see the finished product. pist a video of it when its done would love to see. you should even deploy it with netlify to learn the whole live deployment flow

1 Like

I have it with Vercel https://coin-exchange-qjwtsyb45-rostyslavdzhohola.vercel.app/

I was able to figure out how to hide the main balance on my own, but had to watch the videos to figure out how to hide or change the columns. Instead of hiding the balance column, I replaced values with *** like some central exchanges do.

App.js
import './App.css';
import React from 'react';
import CoinList from './components/CoinList/CoinList';
import AccountBalance from'./components/AccountBalance/AccountBalance';
import AppHeader from './components/AppHeader/AppHeader';

class App extends React.Component {
  state = {
    balance: 10000,
    showBalance: true,
    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
      },
    ]
  }

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

  handleRefresh = (valueChangeTicker) => {
    const newCoinData = this.state.coinData.map( function( {ticker, name, price, balance} ) {
      let newPrice = price;
      if ( valueChangeTicker === ticker ) {
        const randomPercentage = 0.995 + Math.random() * 0.01;
        newPrice = newPrice * randomPercentage;
      }
      return {
        ticker,
        name,
        price: newPrice,
        balance
      }
    });
      this.setState({ coinData: newCoinData });
  }

    render() {
      return (
        <div className="App">
          <AppHeader />
            <AccountBalance 
              amount={this.state.balance} 
              showBalance={this.state.showBalance} 
              handleChangeBalance={this.handleChangeBalance} />
            <CoinList 
              coinData={this.state.coinData} 
              handleRefresh={this.handleRefresh} 
              showBalance={this.state.showBalance} />
        </div>
      );
    }
}

export default App;
AccountBalance.jsx
import React, { Component } from 'react'
import PropTypes from 'prop-types';
import './AccountBalance.css';

export default class AccountBalance extends Component {
    render() {
        const buttonText = this.props.showBalance ? 'Hide Balance' : 'Show Balance';
        let balanceToggle = null;
        if (this.props.showBalance) {
            balanceToggle = <>Account Balance: ${this.props.amount}</>;
        }
        return (
            <section className="AccountBalance"> 
                    <button className="BalanceButton" 
                        onClick={this.props.handleChangeBalance}> 
                        {buttonText} 
                    </button>
                    {balanceToggle}
            </section>
        );
    }
}

AccountBalance.propTypes = {
    amount: PropTypes.number.isRequired
}
CoinList.jsx
import React, { Component } from 'react'
import styled from 'styled-components'
import Coin from '../Coin/Coin';

const Table = styled.table`
  margin: 25px auto 25px auto;
  display: inline-block;
  padding: 5px;
`;

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( ({name, ticker, price, balance}) =>
                <Coin key={ticker} 
                        handleRefresh={this.props.handleRefresh}
                        name={name} 
                        ticker={ticker} 
                        balance={balance}
                        showBalance={this.props.showBalance}
                        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;
`;

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

    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> : <Td>******</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
}
AppHeader.jsx
import React, { Component } from 'react';
import logo from './logo.svg';
import '../AccountBalance/AccountBalance.css'

export default class AppHeader extends Component {
  render() {
    return (
        <header className="App-header">
            <img src={logo} alt="React Logo" className="App-logo" />
            <h2 className="App-title">Coin Exchange</h2>
        </header>
    )
  }
}
AccountBalance.css
.AccountBalance {
    padding-top: 1rem;
    padding-bottom: 1rem;
    border-bottom: .1rem;
    border-bottom-style: solid;
    border-bottom-color: white;
    font-weight: bold;
    background-color: rgb(12, 12, 167);
    align-items: flex-start;
    display: flex;
}

.BalanceButton {
    margin-right: 1rem;
    margin-left: 1rem;
    padding: .25rem;
    font-weight: bold;
}
App.css
.App {
  text-align: center;
  background-color: rgb(0, 6, 47);
  color: white;
}

.App-logo {
  height: 4rem;
  pointer-events: none;
}

.App-header {
  background-color: #282c34;
  min-height: 10vh;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  font-size: calc(10px + 2vmin);
  color: white;
  border-bottom: .5rem;
  border-bottom-style: solid;
  border-bottom-color: #61dafb;
}

.App-title {
  font-size: 2rem;
}

.App-link {
  color: #61dafb;
}


Hi everyone :slight_smile:

The full code is here in my Github repo:
https://github.com/CodingInLondon/moralisacademy-react/tree/b9200c91f6634671c281b56e3301857246c9ee48/coin-exchange

AccountBalance.jsx now has some conditional code to hide the balance amount:

export default class AccountBalance extends Component{

    constructor(props){
        super(props);

        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(event){
        event.preventDefault();

        this.props.handleHideBalance();

    }

    render(){
        const buttonText = this.props.showBalance ? 'Hide Balance': 'Show Balance';

        return (
            <Section>
              <form action="#" method="POST">
                <button onClick={this.handleClick}>{buttonText}</button>
              </form>
              {this.props.showBalance && (
                <span style={{ marginLeft: '1rem' }}>Balance: ${this.props.amount}</span>
              )}
            </Section>
          );
          
        
    }

}

The render method in App.js passes the showBalance flag to the CoinList component:

 render() {
    return (
      <AppStyle>
        <AppHeader />
        <AccountBalance showBalance={this.showBalance} amount={this.state.balance}  handleHideBalance={this.handleHideBalance}/>
        <CoinList showBalance={this.showBalance} coinData={this.state.coinData} handleRefresh={this.handleRefresh}/>
      </AppStyle>
    );
  }

CoinList forwards the flag to Coin:

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

…and Coin uses a condition to hide the balance amount in the Balance column. Imported the react-icons package to display a shut eye in place of the balance amount:

  render() {
    return (
      <Tr>
        <td>{this.props.name}</td>
        <td>{this.props.ticker}</td>
        <td>{this.props.price.toFixed(2)}</td>
        <td>{this.props.showBalance ? `$${this.props.balance}` :             
          <CenteredIcon>
            <FiEyeOff />
          </CenteredIcon>}</td>        
        <td>
          <form action="#" method="POST">
            <button onClick={this.handleClick}>Refresh</button>
          </form>
        </td>
      </Tr>
    )
  }

Hi Guys,
When I added the coinpaprika link to the code, I got the following punch of errors and my page can’t be reached when I run npm start

my App.js code

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

const Div = styled.div`
text-align: center;
background-color: rgb(30, 131, 167) ;
color: rgba(124, 15, 15, 0.999);
`;
const COIN_COUNT = 10;
class App extends React.Component {
  state = {
    balance: 10000,
    showBalance : true,
    coinData: [
      // {
      // name: "Bitcoin",
      // ticker: "BTC",
      // balance: 0.3,
      // price: 29289.25
      // },{
      // name: "Ethereum",
      // ticker:"ETH",
      // balance: 3,
      // price: 1825.75
      // },
      // {
      // name: "Tether",
      // ticker: "USDT",
      // balance: 25,
      // price: 1.10
      // },
      // {
      // name: "Ripple ",
      // ticker: "XRP",
      // balance: 0,
      // price: 0.02
      // },
      // {
      //   name: "Binance",
      //   ticker: "BNB",
      //   balance: 0.55,
      //   price: 240.9
      // }   
      
    ]
  }
 componentDidMount = () =>{
  axios.get('https://api.coinpaprika.com/v1/coins')
       .then( response => {
        let coinData = response.data.slice(0, COIN_COUNT).map(function(coin){
         return{
          key: coin.id,
          name:coin.name,
          ticker: coin.symbol,
          balance: '-',
          price: '-'

         }
        });
        console.log('Setting the state...');
        this.setState({ coinData });
        console.log('Done setting the state');
       });
       console.log('componentDidMount is DONE');
       debugger;
 }

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

  handleRefresh = (valueChangeTicker) =>{
    const newCoinData = this.state.coinData.map( function ( values ) {
    let newValues = {...values };
     if (valueChangeTicker === values.ticker) { 
      const randomPercentage = 0.995 + Math.random() * 0.01;
      newValues.price *= randomPercentage;
     }
      return newValues;   
      
    });
    this.setState ({coinData: newCoinData});
  }
  render(){
    return (
      <Div>
        <HeaderApp/>
        <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;