Coding exercise - Rewrite the CoinList

Welcome to the thread to discuss the exercise - Rewrite the CoinList

Coding exercise: Rewrite the CoinList and AccountBalance components into functional components.

CoinList.jsx:

export default function CoinList(props) {

    return (

       <Table>

      <thead>

          <tr>

            <th>Name</th>

            <th>Ticker</th>

            <th>Price</th>

            {props.showBalance ? <th>Balance</th> : null}

            <th>Actions</th>

          </tr>

      </thead>

      <tbody>

      {

        props.coinData.map( ({key, name, ticker, price, balance}) => 

          <Coin key={key}

            handleRefresh={props.handleRefresh} 

            name={name} 

            ticker={ticker}

            showBalance={props.showBalance}

            balance ={balance} 

            price={price} 

            tickerId={key} /> 

        )

      }

      </tbody>

  </Table>

    )

}

AccountBalance.jsx:

export default function AccountBalance(props) {

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

    let content = null;

    if (props.showBalance) {

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

    }

    return (

        <Section>

          {content}

          <button onClick={props.handleBalanceVisabilityChange}>{buttonText}</button>  

        </Section>

    );

}

This was hard until I realized the assignment was only for the List and AccountBalance components. Still wrapping my head around hooks. Got partway through converting the App component as well. The components with only props are simple.

CoinList
export default function CoinList(props) {

  return (
    <>
      <Table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Ticker</th>
            {props.showBalance ? <th>Balance</th> : null}
            <th>Price</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          {
            props.coinData.map(({ key, name, ticker, balance, price }) =>
              <Coin key={key}
                handleRefresh={props.handleRefresh}
                name={name}
                ticker={ticker}
                balance={balance}
                showBalance={props.showBalance}
                price={price} />)
          }
        </tbody>
      </Table>
    </>
  )
}
AccountBalance
export default function AccountBalance(props) {

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

    let balance = props.showBalance ?
        <span>Balance: ${props.amount}</span>
        : null;

    return (
        <Section>
            {balance}
            <BtnBalance onClick={props.handleToggleShowBalance}>{buttonText}</BtnBalance>
        </Section>
    );
}

1 Like

Coding exercise: Rewrite the CoinList and AccountBalance components into functional components.

CoinList.jsx
import React 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 function CoinList(props) {
  return (
    <Table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Ticker</th>
          {props.showBalance ? <th>Balance</th> : null}
          <th>Price</th>
          <th>Action</th>
        </tr>
      </thead>
      <tbody>
        {
          props.coinData.map(({ key, name, ticker, balance, price }) =>
            <Coin
              key={key}
              id={key}
              name={name}
              handleRefresh={props.handleRefresh}
              ticker={ticker}
              showBalance={props.showBalance}
              balance={balance}
              price={price}
            />
          )
        }
      </tbody>
    </Table>
  )

}
AccountBalance.jsx
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const Section = styled.section`
    /*border: 1px solid red;*/
    margin: 20px auto 0 auto;
    padding-left: 1.5 rem 0 1.5rem 5rem;
    width: 98vw;
    max-width: 780px;
    font-size: 2rem;
    text-align: left;
`;

const Button = styled.button`
    margin: 10px auto 0 auto;
    float: right;
    border: none;
    background-color: #282c34;
    color: #61dafb;
    font-size: 1.4rem;
    :active {
        background: #0053ba;
    }
    :hover {
        border: 1px solid #cccccc;
        border-radius: 3px;
        cursor: pointer;
    }
`;

export default function AccountBalance(props) {

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

    const toggleBalance = props.showBalance ?
        <span><strong>Balance : </strong>$ {props.amount}</span> : null;


    return (
        <Section className="balance">
            {toggleBalance}
            <Button onClick={props.handleToggleBalance}>{buttonText}</Button>
        </Section>
    );
}


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

Hey @zsolt-nagy, I did some digging into when it’s best to use functional components versus class components. Since the React 16.8 Hooks update, you can use both state and lifecycle methods (or akin behavior) within functional components. I’m curious as to what benefits class components now give.

My code:

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

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

export default function CoinList(props) {
    let balance = props.showBalance ? <th>Balance</th> : '';
      return(
        <Table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Ticker</th>
              {balance}
              <th>Price</th>
              <th>Actions</th>
            </tr>
          </thead>
            <tbody>
              {
              props.coinData.map( ({key, name, ticker, price, balance}) =>
                <Coin key={key}
                handleRefresh={props.handleRefresh}
                name={name}
                ticker={ticker}
                showBalance={props.showBalance}
                balance={balance}
                price={price}
                tickerId={key}
              />
              )
              }
            </tbody>
        </Table>
    )
}
AccountBalance
import React 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 function AccountBalance(props) {
    let showBal = props.showBalance ? <>AccountBalance: ${props.amount}</> : '';
    const buttonText = props.showBalance ? 'Hide Balance' : 'Show Balance';
    return (
        <Section>
            { showBal }
            <button onClick={props.handleBalance}> 
                {buttonText} 
            </button> 
        </Section>
    );
}


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

To give you a big one, it’s backwards compatibility. Big companies have a lot of legacy code, and you need to live with legacy, including abstractions built on top of class components.

In case of a green field project, you get the freedom of choice to go functional only if you prefer, and I am 99% confident you won’t miss much.

1 Like

Following the recipe.

1 Like
CoinList.jsx
import React 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 function CoinList(props) {
  let balanceHeader = props.showBalance ? <th>Balance</th> : null;
  return (
    <Table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Ticker</th>
          <th>Price</th>
          {balanceHeader}
          <th>Action</th>
        </tr>
      </thead>
      <tbody>
        {
          props.coinData.map(({ key, name, ticker, balance, price }) =>
            <Coin
              key={key}
              coinId={key}
              handleRefresh={props.handleRefresh}
              showBalance={props.showBalance}
              name={name}
              ticker={ticker}
              balance={balance}
              price={price} />
          )
        }
      </tbody>
    </Table>
  )
}
AccountBalance.jsx
import React, { Component } from "react";
import PropTypes from 'prop-types';
import styled from "styled-components";

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

export default function AccountBalance(props) {
    const handleClick = (event) => {
        event.preventDefault();
        props.handleRefreshShowBalance(!props.showBalance);
    }
    const buttonText = props.showBalance ? "Hide Balance" : "Show Balance";
    const balanceText = props.showBalance ? <>Balance: ${props.amount}</> : null;
    return (
        <Section>
            {balanceText}
            <button onClick={handleClick}>{buttonText}</button>
        </Section>
    );
}

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

CoinList.jsx:

import React 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 function Coinlist(props) {
       return (
        
       <Table>
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Ticker</th>
                    <th>Price</th>
                    {props.showBalance ? <th>Balance</th> : null}
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
              {
                props.coinData.map( ({key,name,ticker,price,balance}) =>
                   <Coin key={key} 
                   handleRefresh={props.handleRefresh}
                   name={name} 
                   ticker={ticker} 
                   showBalance ={props.showBalance}
                   balance={balance}
                   price={price} 
                   tickerId={key}/>
                   )
              }

            </tbody>   
        </Table>
        
        )

}


1 Like

AccountBalance.jsx:



import React 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 function AccountBalance(props) {
    
        const buttonText = props.showBalance ? 'Hide Balance' : 'Show Balance';
        let content = null;
        if(props.showBalance) {
            content =  <>Balance: ${props.amount}</>;
        }
        return ( 
            <Section>
             {content}
        <button onClick={props.handleBalanceVisabilityChange}>{buttonText}</button>
            </Section>
        );
    

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

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


export default function CoinList(props) {
    // render as a table of coins
    return (
        <div label="current prices">
            <Table >
                <CoinListThead showBalance={props.showBalance}/>
                <tbody>
                    {
                        props.coinData.map( ({coinid, name, ticker, price, balance }) =>
                        <Coin 
                            handleRefresh={props.handleRefresh}
                            key={coinid}
                            coinid={coinid} 
                            name={name} 
                            ticker={ticker} 
                            balance={balance}
                            showBalance={props.showBalance}
                            price={price} />
                        )  
                    }
                </tbody>
            </Table>
        </div>
    )
}

and account balance:

import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'

// need to use the `` quotes and add some css
// properties or it does not work at all
const Section = styled.section`
    font-size: 2rem;
    text-align: center;
    padding: 1rem 1rem 1rem 7rem;
`;

const Button = styled.button`
    border: 3px solid blue;
    background-color: black;
    color:white;
    border-radius: 10px;
    font-size: 18px;
    text-align: center;
    width: 150px;
`;

/**
 * displaces the account balance.
 */
export default function AccountBalance(props) {
 
    const handleClick = (event) => {
        event.preventDefault();
        props.handleBalanceShowHide();
    }

    // TODO refactor this into a FiatAmount component
    const currencyOptions = {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
    }

    // format the local currency options.
    // TODO turn the amount into a compoent FiatAmount that can format to a given currency format.
    const getAmount = () => { 
        return (
            props.amount.toLocaleString(undefined, currencyOptions)
        );
    }

    // render function with a styled component depending on the showBlance flag
    // show the balance or not.
    const buttonText = props.showBalance ? 'Hide Balance' : 'Show Balance';
    let balanceContent = null;
    if (props.showBalance) {
        balanceContent = <> Balance: ${getAmount()} &nbsp; </>;
    }
    return (
        <Section>
            {balanceContent}
            <Button onClick={handleClick}>{buttonText}</Button>
        </Section>
    );
    
}

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