Header component exercise

Welcome,

Here you can post and discuss your solutions to the header component exercise.

3 Likes

Not fully convinced I like styled components yet. If you have a lot of styles all the CSS will clutter the component file. Though if that’s the case it might be a hint you need to refactor into multiple components anyway.

App

Since you can name the styled components whatever your want I called it Content instead of div.

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

class App extends React.Component {

// constructor same as before

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

Moved all the styles into styled components and removed App.css.
EDIT: forgot to remove the classes as they are now redundant.

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


const Header = styled.header`
  background-color: #282c34;
  min-height: 20vh;
  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 class AppHeader extends Component {
  render() {
    return (
      <>
        <Header>
          <Img src={logo} alt="React logo" />
          <H1>Coin Exchange</H1>
        </Header>
      </>
    )
  }
}

3 Likes

//App.js
import React from ‘react’;
import CoinList from ‘./components/CoinList/CoinList’;
import AccountBalance from ‘./components/AccountBalance/AccountBalance’;
import Header from ‘./components/Header/Header’;
import styled from ‘styled-components’

const Div= styled.divtext-align: center; background-color: #61dafb; color: white;;

<Div >
  <Header />   
  <AccountBalance amount={this.state.balance}/>
  <CoinList        coinData={this.state.coinData}/>                      
</Div>

//Header.jsx
import React, { Component } from ‘react’;
import logo from ‘…/…/logo.svg’;
import styled from ‘styled-components’

const Img= styled.imgheight: 8rem; pointer-events: none; ;
const AppHeader= styled.header background-color: #282c34; min-height: 20vh; display: flex; flex-direction: row; align-items: center; justify-content: center; color: white; ;

const H1= styled.h1 font-size: 4rem; ;

        <AppHeader>
        <Img src={logo}  alt="logo" />
          <H1 >
            Coin Exchange
          </H1> 
        </AppHeader>          

//CoinList.jsx
import React, { Component } from ‘react’;
import Coin from ‘…/coin/coin’;
import styled from ‘styled-components’

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

        <Table>
      <thead>
          <tr>
              <th>Name</th>
              <th>Ticker</th>
              <th>Price</th>
          </tr>
      </thead>
      <tbody>
      {this.props.coinData.map(({name, ticker, price}) =>  (
       <Coin key={ticker} name={name} ticker={ticker} price={price} />
       ))}  
     </tbody>
  </Table>

You have a point regarding refactoring.

Think about it this way: in 2011, I heard about Bitcoin, didn’t do anything about it, I thought it was another E-Gold that would perish due to governments. In 2014, I heard about React, I thought it violated separation of concerns by placing markup in JavaScript. So I wasn’t an early adopter and waited until 2016 or so, when it was evident that we can’t even hire if we don’t move to React. Now comes styled components… :slight_smile: It has its pros and cons, but if you think about it deeply, it’s not as bad as it looks like at first glance, and solves quite a lot of problems not even Sass or CSS Architecture patterns address.

3 Likes

Good call formatting code-responses this way, @mayjer. It’s way more convenient to navigate :slight_smile:

ExchangeHeader
import React, { Component } from 'react';
import styled from 'styled-components';
import logo from '../logo.svg';

const Header = styled.header`
    background-color: #282c34;
    min-height: 20vh;
    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;
`;
App

i

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

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

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

class App extends React.Component {
  // extraneous constructor data ...
  render() {
    return (
      <Div>
        <ExchangeHeader />
        <AccountBalance amount={this.state.balance} />
        <Table>
          <CoinList coinData={this.state.coinData} />
        </Table>
      </Div>
    );
  }
}
1 Like

Before continuing with the course, create a new Header component and abstract all styling and functionality in your new component.
As an optional exercise, if you prefer using styled components, make sure that all css declarations in App.css are all moved to styled component css declarations.

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


const DivApp = 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,
      coinData: [
        {
          name: "Bitcoin",
          ticker: 'BTC',
          price: 9999.9
        },
        {
          name: "Ethereum",
          ticker: 'ETH',
          price: 274.9
        },
        {
          name: "Tether",
          ticker: 'USDT',
          price: 1
        },
        {
          name: "Ripple",
          ticker: 'XRP',
          price: 0.2
        },
        {
          name: "Bitcoin Cash",
          ticker: 'BCH',
          price: 298.99
        },
        {
          name: "Ethereum",
          ticker: 'ETH',
          price: 274.9
        },
        {
          name: "Ethereum",
          ticker: 'ETH',
          price: 274.9
        }
      ]
    }
  }

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

export default App;```
ExchangeHeader.jsx
import React, { Component } from 'react';
import logo from '../../logo.svg';
import styled from 'styled-components';
const Img = styled.img`
    height: 8rem; /*40vmin;*/
    pointer-events: none;
    `;

const Header = styled.header`
    background-color: #282c34;
    min-height: 20hv;/* 100vh;*/
    display: flex;
    flex-direction: row; /*column;*/
    align-items: center;
    justify-content: flex-start; /*center;*/
    font-size: 36px; /*calc(10px + 2vmin);*/
    color: white;
  `;

const H1 = styled.h1`
    font-size: 4rem;
    `;

export default class ExchangeHeader extends Component {

    render() {
        return (
            <Header>
                <Img src={logo} alt="React logo" />
                <H1>
                    Coin Exchange
                </H1>
            </Header>
        )
    }
}
CoinList.jsx
import React, { Component } from 'react'
import Coin from '../Coins/Coin';
import styled from 'styled-components';

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

export default class CoinList extends Component {

    render() {
        return (
            <Table> 
            <thead>
              <tr>
                <th>Name</th>
                <th>Ticker</th>
                <th>Price</th>
              </tr>
            </thead>
            <tbody>
              {
                this.props.coinData.map( ({name, ticker, price}) =>
                  <Coin key={ticker} name={name} ticker={ticker} price={price} 
                  />
                )
              }
            </tbody>
          </Table>
        )
    }
}

Step-by-step:
1.) Removed extraneous folders from components/
2.) Separated header into its own component.
3.) Added prop-types checking to header component.
4.) Dissolved (most of) App.css into styled header component.

I think the logo should be its own component too but I backed off of that trail to stay in sync with the course work. I ran into a rabbit hole researching how to move the css logo animation into React. There seem to be many ways to do it. I suppose that’s why you axed the animation early on to avoid the quagmire. For now I just moved the animations into their own .css under components/. I do hope to properly learn animations in React soon, from you or otherwise.

import React from 'react';
import logo from '../logo.svg';
import styled from "styled-components";

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 Img = styled.img`
    height: 8rem;
    pointer-events: none;
`;

const H1 = styled.h1`
    font-size: 4rem;
`;

export default class CoinHeader extends React.Component {
    render() {
        return (
            <Header>
                <Img src={logo} alt="logo" />
                <H1>Coin Exchange</H1>
            </Header>
        )
    }
}

First Im up and running again! Fixed my styled-components problem!!!

and second… Im moving forward again with my current exercises! Happy isn’t the word for it!!! :wink:

4 Likes

App:

 render () {
      return (
        <div className="App">
          <Header />
          <AccountBalance amount={this.state.balance} />
          <Coinlist coinData={this.state.coinData} />
        </div>
      );
    }

Header:

import React, { Component } from 'react';
import logo from './logo.svg';
import './Header.css'

export default class Header extends Component {
    render() {
        return (
            <header className="App-header">
            <img src={logo} alt="react logo" className="App-logo" />
            <h1 className="app-title">
              Coin Exchange
            </h1>
          </header>
        )
    }
}
3 Likes

import React, { Component } from ‘react’
import logo from ‘./logo.svg’;
import styled from ‘styled-components’

const Header = styled.header`
background-color: #282c34;
min-height: 20vh;
display: flex;
flex-direction: row;
align-items: center;
justify-content: left;

color: white;

`;

const Img = styled.img height: 4rem; pointer-events: none;;

const H1 = styled.h1 font-size: 4rem;;

export default class AppHeader extends Component {

render() {
    return (
    <Header className="App-header">
      <Img src={logo} alt="react logo" className="App-logo" />
      <h1 className="apt-title">Coin Exchange</h1>
    </Header>
    );
}

}

1 Like
AppHeader
import React, { Component } from 'react'
import styled from 'styled-components'


const Header = styled.header`
  min-height: 20vh;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  font-size: 24px;
  text-align: center;
  color: white;
`;

export default class AppHeader extends Component {
    render() {
        return (
          <Header>
            <img src='./polka-dot.png' alt="Polkadot logo" />
            <h1>
              Polkadot Ecosystem prices
            </h1>
          </Header>
        )
    }
}
2 Likes
import React, { Component } from 'react'
import logo from '../logo.svg';
import styled from 'styled-components';

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

const Title = styled.h1`
font-size: 4rem;
`;

const Img = styled.img`
height: 20rem;
pointer-events: none;
`;

export default class Header extends Component {
    render() {
        return (
        <Wrapper>
          <Img src={logo} alt="React logo" />
          <Title>
            Coin Exchange
          </Title>
        </Wrapper> 
        )
    }
}

Can’t quite work out how to keep the rotation on the logo, which is bugging me.

Check out the original App.css selectors, and see how the image or its container got selected and rotated. You need to make sure to replicate the exact same structure in styled components to reproduce first the selection of the right component to rotate, then to execute the keyframe animation.

1 Like

Just an example:

3 Likes

AppHeader.jsx:

App.js:

image

image

CoinList.jsx:

Outcome:

2 Likes

In components folder I created Header / Header.jsx :

import React, { Component } from 'react';
import logo from '../../logo.svg';

export default class Header extends Component {
    render() {
        return (
            <header className="App-header">
                <img src={logo} alt="React logo" className="App-logo"/>
                <h1 className="App-title">
                    Coin exchange
                </h1>
            </header>
        )
    }
}

In App.js I added < Header /> to the body of render():

render() {

    return (
      <div className="App">
        <Header />
        <AccountBalance amount={this.state.balance} />
        <CoinList coinData={this.state.coinData} />
      </div>
    );
  }

My header looks the same, so apparently it still gets the styling from App.css :

1 Like

App

render ( ) {
return (
<AppDiv>
<AppHeader> </AppHeader>
<AccountBalance amount = {this.state.balance} />
<CoinList coinDate = {this.state.coinDate} > </CoinList>
</AppDiv>
);
}

Header

import React, {Component} from 'react';
import logo from '../../logo.svg';
import '../../App.css';
export default class Header extends Component {
render ( ) {
return (
<header className = "App-header">
<img src = {logo} className = "App-logo" />
<h1 className = "app-title">
Coin Exchange 
</h1>
</header>
)
}
}
2 Likes

App.js

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

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {...}
  }
  render() {
    return (
      <div className="App">
        <Header/>
        <AccountBalance amount={this.state.balance}/>
        <CoinList coinData={this.state.coinData}/>
      </div>
    );
  }
}

Header.jsx (logo was moved to same folder).

import React, { Component } from 'react'
import logo from './logo.svg'

export default class Header extends Component {
    render() {
        return (
            <header className="App-header">
                <img src={logo} alt='React Logo' className='App-logo'></img>
                <h1 className='App-title'>
                    Coin Exchange
                </h1>
            </header>
        )
    }
}
2 Likes

Hi @muradawad, You forgot the starting tag for AppDiv in this code. It should be

<AppDiv>
<AppHeader> </AppHeader>
<AccountBalance amount = {this.state.balance} />
<CoinList coinDate = {this.state.coinDate} > </CoinList>
</AppDiv>

Also, you forgot to end the img tag here,

It should have been like this –
<img src={logo} className ="App-logo" />

Hope this fixes your syntax issues.

2 Likes