Welcome to the thread to discuss the exercise - Rewrite the CoinList
Coding exercise: Rewrite the CoinList and AccountBalance components into functional components.
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.
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>
</>
)
}
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>
);
}
Coding exercise: Rewrite the CoinList and AccountBalance components into functional components.
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>
)
}
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:
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>
)
}
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.
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>
)
}
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
}
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>
)
}
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>
);
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()} </>;
}
return (
<Section>
{balanceContent}
<Button onClick={handleClick}>{buttonText}</Button>
</Section>
);
}
AccountBalance.protoType = {
amount: PropTypes.number.isRequired
}
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>Action</th>
</tr>
</thead>
<tbody>
{
props.coinData.map( ({key, name, ticker, price, balance}) =>
<Coin key={key}
handleRefresh={props.handleRefresh}
name={name}
id = {key}
price={price}
ticker={ticker}
showBalance={props.showBalance}
balance={balance}
/>
)
}
</tbody>
</Table>
)
}
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components'
const Section = styled.section`
width: 100vh;
font-size: 3rem;
text-align: right;
color: white;
`;
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.handleVisibilityChange}>{buttonText}</button>
</Section>
)
}
AccountBalance.propTypes = {
amount: PropTypes.number.isRequired
}
CoinList:
import React from 'react';
import Coin from '../Coin/Coin';
import styled from 'styled-components';
const Table = styled.table`
margin: 50px auto 50 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}
balance = {balance}
showBalance ={props.showBalance}
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) {
const buttonText = props.showBalance ? 'Hide balance' : 'Show Balance';
return (
<Section>
{props.showBalance ? <> Balance: ${props.amount} </>: null}
<button onClick={props.handleToggleShowBalance}>{buttonText}</button>
</Section>
);
}
AccountBalance.propTypes = {
amount: PropTypes.number.isRequired
}
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
const Section = styled.section`
font-size: 2rem;
text-align: right;
padding: 1.5rem 5rem 1.5rem 0;
color: white;
`;
export default function AccountBalance(props) {
const buttonText = props.showBalance ? 'Hide Balance' : 'Show Balance';
let balanceToggle = props.showBalance ? <> Balance: ${props.amount} </> : null;
return (
<Section>
{balanceToggle}
<button onClick={props.handleToggleBalance}>{buttonText}</button>
</Section>
);
}
AccountBalance.propTypes = {
amount: PropTypes.number.isRequired
}
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) {
let balanceToggle = props.showBalance ? <th> Balance </th> : null;
return (
<Table>
<thead>
<tr>
<th>Name</th>
<th>Ticker</th>
<th>Price</th>
{balanceToggle}
<th>Action</th>
</tr>
</thead>
<tbody>
{
props.coinData.map ( ({key, name, ticker, price, balance}) =>
<Coin
key= {key}
id = {key}
handleRefresh={props.handleRefresh}
showBalance = {props.showBalance}
name={name}
ticker={ticker}
balance= {balance}
price={price} />
)
}
</tbody>
</Table>
)
}
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}) =>{
return <Coin key={key} id={key} handleRefresh={props.handleRefresh} showBalance={props.showBalance} name={name} ticker={ticker} balance={balance} price={price}></Coin>
})
}
</tbody>
</Table>
)
}
export default function AccountBalance(props) {
const handleClick = (event) => {
event.preventDefault();
props.handleShowBalance(props.showBalance);
}
const buttonText = props.showBalance ? 'Hide Balance' : 'Show Balance';
return (
<Section>{props.showBalance ? `Balance: $${props.amount}` : null}
<Button onClick={handleClick}>{buttonText}</Button>
</Section>
);
}
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.6rem;
`;
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
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
const Section = styled.section`
font-size: 3rem;
text-align: center;
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.handleBalanceVisibilityChange}>{buttonText}</button>
</Section>
);
}
AccountBalance.propTypes = {
amount: PropTypes.number.isRequired
}
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.8 rem;
';
export default function CoinList (props) {
let balanceHeader =props.showBalance?<th>Balance</th>:null;
return (
<Table>
<thread>
<tr>
<th>Name</th>
<th>Ticker</th>
<th>Ticker</th>
<th>Price</th>
{balanceHeader}
<th>Acion</th>
</tr>
</thread>
<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
import React from 'react'
import Prop Types from 'prop-types'
import styled from 'styled-components';
const section = styled.section'
font-size : 2 rem;
text-align : middle;
Padding : 1.6 rem 0 1.6 rem 6 rem;
';
export default function Account Balance (props) {
const buttonText = props.showBalance? 'HideBalance':
'showBalance';
let balance Toggle = props.showBalance?< > Balance:
$ {props.amount} </>:null;
return(
<section>
{balance Toggle}
<button on Click = {props.handleToggleBalance}>
{button Text} </button>
</Section>
);
}
AccountBalance.propTypes = {
amount:PropTypes.number.isRequired}
import React from 'react';
import Coin from '../Coin/Coin';
import styled from 'styled-components';
const Table = styled.table`
margin: auto;
display: inline-block;
font-size: 1.4 rem
`;
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>
)
}
import React from 'react';
import styled from 'styled-components';
import propTypes from 'prop-types';
const Section = styled.section`
font-size: 2rem;
text-align: left;
padding: 1.5rem 5rem 1.5rem 5rem;
`;
const Button = styled.button`
font-size: 1.6rem;
margin: 1.5rem 0 1.5rem 5rem;
background-color: #282c34;
color: #fff;
border: 1px solid #fff;
border-radius: 5px;
`;
export default function AccountBalance (props) {
return (
<Section>
{props.showBalance ? <>Account Balance: ${props.amount}</> : null}
<Button onClick={props.handleBalanceDisplay}>
{props.showBalance ? 'Hide Balance' : 'Show Balance'}
</Button>
</Section>
);
}
AccountBalance.propTypes = {
amount: propTypes.number.isRequired
}
I took the liberty to also rewrite:
import React from 'react'
import logo from './logo.svg'
import styled from 'styled-components';
const Header = styled.header`
background-color: #282c34;
min-height: 10vh;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
font-size: 36px;
color: white;
`;
const Img = styled.img`
height: 8rem;
pointer-events: none;
`;
const H1 = styled.h1`
font-size: 4rem;
`;
export default function ExchangeHeader () {
return (
<Header>
<Img src={logo} alt='React Logo'></Img>
<H1>
Coin Exchange
</H1>
</Header>
)
}
CoinList
import React from 'react'
import styled from 'styled-components';
import Coin from '../Coin/Coin';
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>
)
}
AccountBalance
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
const Section = styled.section`
margin: 20px auto 10px auto;
border: 1px solid #cccccc;
width: 40vh;
`;
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.handleBalanceVisibilityChange}>{buttonText}</button>
</Section>
);
}
AccountBalance.propTypes = {
amount: PropTypes.number.isRequired
}
CoinHeader
import React from 'react'
import logo from './logo.svg';
import styled from 'styled-components';
const Img = styled.img`
height: 8rem;
pointer-events: none;
`;
const Header = styled.header`
background-color: #282c34;
min-height: 20vh;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
color: white;
`;
const H1 = styled.h1`
font-size: 4rem;
`;
export default function CoinHeader() {
return (
<Header>
<Img src={logo} alt="React logo" />
<H1>
Coin Exchange
</H1>
</Header>
)
}