Day_16 has been added

pull/72/head
asabeneh 4 years ago
parent 384a270937
commit ad6b501b61

1
.gitignore vendored

@ -2,5 +2,6 @@ draft.md
react-for-everyone.md
component.md
draft
17_React_Router

@ -21,6 +21,7 @@
- [Third Party Packages](#third-party-packages)
- [NPM or Yarn](#npm-or-yarn)
- [node-sass](#node-sass)
- [CSS modules](#css-modules)
- [axios](#axios)
- [react-icons](#react-icons)
- [moment](#moment)
@ -34,11 +35,11 @@
# Third Party Packages
There are more than 1.4M JavaScript on npm registry. By now there is a package for every kind of problem. We do not have to create the wheel instead we have to know how to use the wheel. In this section, we will learn how to use npm packages and also we will implement most common package for React applications. As of October 10, 2020, the npm registry popular packages, total number of packages, downloads per week and downloads per month.
There are more than 1.4M JavaScript packages on npm registry. By now there is a package almost for every kind of problem. We do not have to create the wheel instead we have to know how to use the wheel. In this section, we will learn how to use npm packages and also we will implement most common package for React applications. As of October 10, 2020, the npm registry popular packages, total number of packages, downloads per week and downloads per month seems as shown below.
![NPM packages](../images/npm_package_day_15.png)
In one way or the other you many need the following packages in your React applications.
In one way or the other you many need the following packages in your React applications. Specially node-sass, moment and axios are important for some projects.
- [node-sass](https://www.npmjs.com/package/node-sass)
- [moment](https://www.npmjs.com/package/moment)
@ -47,18 +48,19 @@ In one way or the other you many need the following packages in your React appli
- [styled-components](https://styled-components.com/)
- [reactstrap](https://reactstrap.github.io/)
- [lodash](https://www.npmjs.com/package/lodash)
- [uuid](https://www.npmjs.com/package/uuid)
## NPM or Yarn
You can use either npm or yarn to install packages. If you want to use [yarn](https://yarnpkg.com) you have install it separately. I would recommend you to stick in one of the package. Don't use both package management tools in one application at the same time.
Let's how to install packages to an application. First we go to the project directory and write the following command.
Let's see how to install packages to an application. First, we go to the project directory and write the following command.
```sh
// syntax, we can use i or install
npm i package-name
// or
yarn add package-name
```
### node-sass
@ -79,9 +81,122 @@ Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react$ yarn add node-sass
After installing node-sass you can start using Sass in React. Create a styles folder and inside this folder create test.scss. Import this file to the component you are working or index.js. You don't need import the node-sass to the component.
```css
/* ./styles/header.scss */
header {
background-color: #61dbfb;
padding: 25;
padding: 10px;
margin: 0;
}
```
```js
// Header.js
import React from 'react'
import './styles/header.scss
const Header = () = (
<header>
<div className='header-wrapper'>
<h1>30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Instructor: Asabeneh Yetayeh</p>
<small>Oct 15, 2020</small>
</div>
</header>
)
export default Header
```
```js
// App.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './styles/header.scss
class App extends Component {
render() {
return (
<div className='App'>
<Header />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### CSS modules
In addition to Sass, it is good to know how to use CSS modules in React. We do not have to install a separate package for a CSS module to use CSS module in React applications. CSS module can be used with Pure CSS or with Sass. The naming convention for CSS module is a specific name followed by dot and module(test.module.css or test.module.scss)
Naming:
```js
// index.js
import './styles/test.scss
// naming for Sass
// naming for CSS
;[name].module.scss[name].module.css
```
```css
/* ./styles/header.module.scss */
.header {
background-color: #61dbfb;
padding: 25;
padding: 10px;
margin: 0;
}
.header-wrapper {
font-weight:500
border: 5px solid orange;
}
```
```js
// Header.js
import React from 'react'
import headerStyles from './styles/header.module.scss
// We can all destructure the class name
const {header, headerWrapper} = headerStyles
const Header = () = (
<header className = {headerStyles.header}>
<div className={headerStyles.headerWrapper}>
<h1>30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Instructor: Asabeneh Yetayeh</p>
<small>Oct 15, 2020</small>
</div>
</header>
)
export default Header
```
```js
// App.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './styles/header.scss
class App extends Component {
render() {
return (
<div className='App'>
<Header />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### axios
@ -167,6 +282,8 @@ const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
We can use axios with await and async functions. In order to implement await and async we need to have separate function outside the componentDidMount. If we implement await and async the error has to be handled by try and catch.
### react-icons
Icons are integral part of a website. To get different SVG icons
@ -277,11 +394,13 @@ class App extends Component {
return (
<div className='App'>
<Header>
<Title>30 Days Of React</Title>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Instructor: Asabeneh Yetayeh</p>
<small>Oct 15, 2020</small>
<div>
<Title>30 Days Of React</Title>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Instructor: Asabeneh Yetayeh</p>
<small>Oct 15, 2020</small>
</div>
</Header>
</div>
)

@ -1,4 +1,4 @@
# 30 Days of React App: Day 14
# 30 Days of React App: Day 15
In the project directory, you can run to start the project

@ -0,0 +1,212 @@
<div align="center">
<h1> 30 Days Of React: Higher Order Component</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Author:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> October, 2020</small>
</sub>
</div>
[<< Day 15](../15_Third_Party_Packages/15_third_party_packages.md) | [Day 17 >>]()
![30 Days of React banner](../images/30_days_of_react_banner_day_16.jpg)
- [Higher Order Component](#higher-order-component)
- [Exercises](#exercises)
- [Exercises: Level 1](#exercises-level-1)
- [Exercises: Level 2](#exercises-level-2)
- [Exercises: Level 3](#exercises-level-3)
# Higher Order Component
The term higher order component is similar to higher order function in JavaScript. In JavaScript, a higher order function is a function that takes another function as a parameter or return another function.
Similar to higher order function, a higher order component takes a component and return another component.
This definition will make sense with examples. Look at the example below for better understand.
```js
// One way of writing a Higher Order Component(HOC)
import React from 'react'
const higherOrderComponent = (Component) => {
return (props) => {
return <Component {...props} />
}
}
```
Most of the time third party libraries use higher order component. For instance redux, react-router-dom and material-u use higher order component.
```js
import React from 'react'
const Button = ({ onClick, text, style }) => {
return (
<button onClick={onClick} style={style}>
{text}
</button>
)
}
const buttonWithStyle = (CompParam) => {
const buttonStyles = {
backgroundColor: '#61dbfb',
padding: '10px 25px',
border: 'none',
borderRadius: 5,
margin: 3,
cursor: 'pointer',
fontSize: 18,
color: 'white',
}
return (props) => {
return <CompParam {...props} style={buttonStyles} />
}
}
const NewButton = buttonWithSuperPower(Button)
class App extends Component {
render() {
return (
<div className='App'>
<Button text='No Style' />
<NewButton text='Styled Button' />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Let's make the buttonWithStyle higher order take more parameter in addition to the component.
```js
import React from 'react'
const Button = ({ onClick, text, style }) => {
return (
<button onClick={onClick} style={style}>
{text}
</button>
)
}
const buttonWithStyles = (CompParam, bgColor = 'default') => {
const colors = [
{
name: 'default',
backgroundColor: '#e7e7e7',
color: '#000000',
},
{
name: 'react',
backgroundColor: '#61dbfb',
color: '#ffffff',
},
{
name: 'success',
backgroundColor: '#4CAF50',
color: '#ffffff',
},
{
name: 'info',
backgroundColor: '#2196F3',
color: '#ffffff',
},
{
name: 'warning',
backgroundColor: '#ff9800',
color: '#ffffff',
},
{
name: 'danger',
backgroundColor: '#f44336',
color: '#ffffff',
},
]
const { backgroundColor, color } = colors.find((c) => c.name === bgColor)
const buttonStyles = {
backgroundColor,
padding: '10px 45px',
border: 'none',
borderRadius: 3,
margin: 3,
cursor: 'pointer',
fontSize: '1.25rem',
color,
}
return (props) => {
return <CompParam {...props} style={buttonStyles} />
}
}
const NewButton = buttonWithSuperPower(Button)
const ReactButton = buttonWithSuperPower(Button, 'react')
const InfoButton = buttonWithSuperPower(Button, 'info')
const SuccessButton = buttonWithSuperPower(Button, 'success')
const WarningButton = buttonWithSuperPower(Button, 'warning')
const DangerButton = buttonWithSuperPower(Button, 'danger')
class App extends Component {
render() {
return (
<div className='App'>
<Button text='No Style' onClick={() => alert('I am not styled yet')} />
<NewButton
text='Styled Button'
onClick={() => alert('I am the default style')}
/>
<ReactButton text='React' onClick={() => alert('I have react color')} />
<InfoButton
text='Info'
onClick={() => alert('I am styled with info color')}
/>
<SuccessButton text='Success' onClick={() => alert('I am succesful')} />
<WarningButton
text='Warning'
onClick={() => alert('I warn you many times')}
/>
<DangerButton
text='Danger'
onClick={() => alert('Oh no, you can not restore it')}
/>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
The is above example is one use case of Higher Order Component. However, its use case is is more than just styling simple button. It has enormous use cases, it allow us to reuse component and enhance a component with style and functionality. In the coming sections, we will cover React Router and we will use HOC and you will not be surprised when you see one component wrap another component.
# Exercises
## Exercises: Level 1
1. What is higher order function
2. What is Higher Order Component
3. What is the difference between higher order function and higher order component?
4. A higher order component can allow us to enhance a component. (T or F)
## Exercises: Level 2
1. Make a higher order component which can handle all the input type.
## Exercises: Level 3
coming
🎉 CONGRATULATIONS ! 🎉
[<< Day 15](../15_Third_Party_Packages/15_third_party_packages.md) | [Day 17 >>]()

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

@ -0,0 +1,5 @@
# 30 Days of React App: Day 16
In the project directory, you can run to start the project
### `npm start`

@ -0,0 +1,34 @@
{
"name": "30-days-of-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500|Roboto:300,400,500&display=swap"
rel="stylesheet"
/>
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>30 Days Of React App</title>
<style>
/* == General style === */
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
line-height: 1.5;
font-family: 'Montserrat';
font-weight: 300;
color: black;
}
.root {
min-height: 100%;
position: relative;
}
.header-wrapper,
.main-wrapper,
.footer-wrapper {
width: 85%;
margin: auto;
}
.header-wrapper,
.main-wrapper {
padding: 10px;
margin: 2px auto;
}
h1 {
font-size: 70px;
font-weight: 300;
}
h2,
h3 {
font-weight: 300;
}
header {
background-color: #61dbfb;
padding: 25;
padding: 10px;
}
main {
padding: 10px;
padding-bottom: 60px;
/* Height of the footer */
}
ul {
margin-left: 15px;
}
ul li {
list-style: none;
}
footer {
position: absolute;
bottom: 0;
width: 100%;
height: 60px;
/* Height of the footer */
background: #6cf;
}
.footer-wrapper {
font-weight: 400;
text-align: center;
line-height: 60px;
}
.user-card {
margin-top: 10px;
}
.user-card > img {
border-radius: 50%;
width: 14%;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
</html>

@ -0,0 +1,13 @@
export const tenHighestPopulation = [
{ country: 'World', population: 7693165599 },
{ country: 'China', population: 1377422166 },
{ country: 'India', population: 1295210000 },
{ country: 'United States of America', population: 323947000 },
{ country: 'Indonesia', population: 258705000 },
{ country: 'Brazil', population: 206135893 },
{ country: 'Pakistan', population: 194125062 },
{ country: 'Nigeria', population: 186988000 },
{ country: 'Bangladesh', population: 161006790 },
{ country: 'Russian Federation', population: 146599183 },
{ country: 'Japan', population: 126960000 },
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -0,0 +1,137 @@
import React, { Component } from 'react'
import axios from '../../../17_React_Router/15_react_router_boilerplate/src/node_modules/axios'
import ReactDOM from 'react-dom'
import moment from '../../../17_React_Router/15_react_router_boilerplate/src/node_modules/moment'
import styled from 'styled-components'
import {
TiSocialLinkedinCircular,
TiSocialGithubCircular,
TiSocialTwitterCircular,
} from '../../../17_React_Router/15_react_router_boilerplate/src/node_modules/react-icons/ti'
const Title = styled.h1`
font-size: 70px;
font-weight: 300;
`
const SubTitle = styled.h2`
font-weight: 300;
`
const Header = styled.header`
background-color: #61dbfb;
padding: 25;
padding: 10px;
margin: 0;
`
class App extends Component {
constructor(props) {
super(props)
console.log('I am the constructor and I will be the first to run.')
this.state = {
firstName: 'John',
data: [],
day: 1,
congratulate: '',
}
}
componentDidMount() {
const API_URL = 'https://restcountries.eu/rest/v2/all'
axios
.get(API_URL)
.then((response) => {
this.setState({
data: response.data,
})
})
.catch((error) => {
console.log(error)
})
}
static getDerivedStateFromProps(props, state) {
return { firstName: props.firstName }
}
shouldComponentUpdate(nextProps, nextState) {
console.log(nextProps, nextState)
console.log(nextState.day)
if (nextState.day > 31) {
return false
} else {
return true
}
}
doChallenge = () => {
this.setState({
day: this.state.day + 1,
})
}
renderCountries = () => {
return this.state.data.map((country) => {
const languageOrLanguages =
country.languages.length > 1 ? 'Langauges' : 'Language'
const formatLanguages = country.languages
.map(({ name }) => name)
.join(', ')
return (
<div>
<div>
{' '}
<img src={country.flag} alt={country.name} />{' '}
</div>
<div>
<h1>{country.name}</h1>
<p>Capital: {country.capital}</p>
<p>
{languageOrLanguages}: {formatLanguages}
</p>
<p>Population: {country.population}</p>
</div>
</div>
)
})
}
componentDidUpdate(prevProps, prevState) {
if (prevState.day == 30) {
this.setState({
congratulate: 'Congratulations,Challenge has been completed',
})
}
console.log(prevState, prevProps)
}
render() {
return (
<div className='App'>
<Header>
<Title>30 Days Of React</Title>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Instructor: Asabeneh Yetayey</p>
<small>Oct 15, 2020</small>
</Header>
<p>This challenge was started {moment('2020-10-01').fromNow()}</p>
<p>The challenge will be over in {moment('2020-10-30').fromNow()}</p>
<p>Today is {moment(new Date()).format('MMMM DD, YYYY HH:mm')}</p>
<h1>React Component Life Cycle</h1>
<h1>Calling API</h1>
<TiSocialLinkedinCircular />
<TiSocialGithubCircular />
<TiSocialTwitterCircular />
<button onClick={this.doChallenge}>Do Challenge</button>
<p>Challenge: Day {this.state.day}</p>
{this.state.congratulate && <h2>{this.state.congratulate}</h2>}
<div>
<p>There are {this.state.data.length} countries in the api</p>
<div className='countries-wrapper'>{this.renderCountries()}</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

@ -0,0 +1,137 @@
import React, { Component } from 'react'
import axios from '../../../17_React_Router/17_react_router_boilerplate/src/node_modules/axios'
import ReactDOM from 'react-dom'
import moment from '../../../17_React_Router/17_react_router_boilerplate/src/node_modules/moment'
import styled from 'styled-components'
import {
TiSocialLinkedinCircular,
TiSocialGithubCircular,
TiSocialTwitterCircular,
} from '../../../17_React_Router/17_react_router_boilerplate/src/node_modules/react-icons/ti'
const Title = styled.h1`
font-size: 70px;
font-weight: 300;
`
const SubTitle = styled.h2`
font-weight: 300;
`
const Header = styled.header`
background-color: #61dbfb;
padding: 25;
padding: 10px;
margin: 0;
`
class App extends Component {
constructor(props) {
super(props)
console.log('I am the constructor and I will be the first to run.')
this.state = {
firstName: 'John',
data: [],
day: 1,
congratulate: '',
}
}
componentDidMount() {
const API_URL = 'https://restcountries.eu/rest/v2/all'
axios
.get(API_URL)
.then((response) => {
this.setState({
data: response.data,
})
})
.catch((error) => {
console.log(error)
})
}
static getDerivedStateFromProps(props, state) {
return { firstName: props.firstName }
}
shouldComponentUpdate(nextProps, nextState) {
console.log(nextProps, nextState)
console.log(nextState.day)
if (nextState.day > 31) {
return false
} else {
return true
}
}
doChallenge = () => {
this.setState({
day: this.state.day + 1,
})
}
renderCountries = () => {
return this.state.data.map((country) => {
const languageOrLanguages =
country.languages.length > 1 ? 'Langauges' : 'Language'
const formatLanguages = country.languages
.map(({ name }) => name)
.join(', ')
return (
<div>
<div>
{' '}
<img src={country.flag} alt={country.name} />{' '}
</div>
<div>
<h1>{country.name}</h1>
<p>Capital: {country.capital}</p>
<p>
{languageOrLanguages}: {formatLanguages}
</p>
<p>Population: {country.population}</p>
</div>
</div>
)
})
}
componentDidUpdate(prevProps, prevState) {
if (prevState.day == 30) {
this.setState({
congratulate: 'Congratulations,Challenge has been completed',
})
}
console.log(prevState, prevProps)
}
render() {
return (
<div className='App'>
<Header>
<Title>30 Days Of React</Title>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Instructor: Asabeneh Yetayey</p>
<small>Oct 15, 2020</small>
</Header>
<p>This challenge was started {moment('2020-10-01').fromNow()}</p>
<p>The challenge will be over in {moment('2020-10-30').fromNow()}</p>
<p>Today is {moment(new Date()).format('MMMM DD, YYYY HH:mm')}</p>
<h1>React Component Life Cycle</h1>
<h1>Calling API</h1>
<TiSocialLinkedinCircular />
<TiSocialGithubCircular />
<TiSocialTwitterCircular />
<button onClick={this.doChallenge}>Do Challenge</button>
<p>Challenge: Day {this.state.day}</p>
{this.state.congratulate && <h2>{this.state.congratulate}</h2>}
<div>
<p>There are {this.state.data.length} countries in the api</p>
<div className='countries-wrapper'>{this.renderCountries()}</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

@ -37,7 +37,8 @@
|12|[Forms](./12_Day_Forms/12_forms.md)|
|13|[Controlled and Uncontrolled Component](./13_Day_Controlled_Versus_Uncontrolled_Input/13_uncontrolled_input.md)|
|14|[Component Life Cycles](./14_Day_Component_Life_Cycles/14_component_life_cycles.md)|
|15|[Styles in React](./15_Third_Party_Packages/15_third_party_packages.md)|
|15|[Third Party Packages](./15_Third_Party_Packages/15_third_party_packages.md)|
|16|[Higher Order Components](./16_Higher_Order_Component/16_higher_order_component.md)|
CONGRATULATIONS FOR MAKING TO THIS FAR

Loading…
Cancel
Save