@ -1,3 +1,6 @@
|
||||
draft.md
|
||||
react-for-everyone.md
|
||||
component.md
|
||||
component.md
|
||||
11_Day_Events
|
||||
12_Day_Forms
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="JSX" />
|
||||
</component>
|
||||
</project>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/30-Days-Of-React.iml" filepath="$PROJECT_DIR$/.idea/30-Days-Of-React.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
@ -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 3
|
||||
|
||||
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>
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,153 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import asabenehImage from './images/asabeneh.jpg'
|
||||
|
||||
// Fuction to show month date year
|
||||
|
||||
const showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return ` ${month} ${date}, ${year}`
|
||||
}
|
||||
|
||||
// Header Component
|
||||
const Header = ({
|
||||
data: {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
},
|
||||
}) => {
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{showDate(date)}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
// TechList Component
|
||||
const TechList = ({ techs }) => {
|
||||
const techList = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techList
|
||||
}
|
||||
|
||||
// User Card Component
|
||||
const UserCard = ({ user: { firstName, lastName, image } }) => (
|
||||
<div className='user-card'>
|
||||
<img src={image} alt={firstName} />
|
||||
<h2>
|
||||
{firstName}
|
||||
{lastName}
|
||||
</h2>
|
||||
</div>
|
||||
)
|
||||
|
||||
// A button component
|
||||
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 18,
|
||||
color: 'white',
|
||||
}
|
||||
|
||||
// Main Component
|
||||
const Main = ({ user, techs, greetPeople, handleTime }) => (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={techs} />
|
||||
</ul>
|
||||
<UserCard user={user} />
|
||||
<Button text='Greet People' onClick={greetPeople} style={buttonStyles} />
|
||||
<Button text='Show Time' onClick={handleTime} style={buttonStyles} />
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
|
||||
// Footer Component
|
||||
const Footer = ({ copyRight }) => (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {copyRight.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
|
||||
// The App, or the parent or the container component
|
||||
// Functional Component
|
||||
const App = () => {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: new Date(), // date needs to be formatted to a human readable format
|
||||
}
|
||||
const date = new Date()
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
// copying the author from data object to user variable using spread operator
|
||||
const user = { ...data.author, image: asabenehImage }
|
||||
|
||||
const handleTime = () => {
|
||||
alert(showDate(new Date()))
|
||||
}
|
||||
const greetPeople = () => {
|
||||
alert('Welcome to 30 Days Of React Challenge, 2020')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
<Main
|
||||
user={user}
|
||||
techs={techs}
|
||||
handleTime={handleTime}
|
||||
greetPeople={greetPeople}
|
||||
/>
|
||||
<Footer copyRight={date} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
@ -0,0 +1,288 @@
|
||||
<div align="center">
|
||||
<h1> 30 Days Of React: Mapping Arrays </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 5](./../05_Day_Props/05_props.md) | [Day 7 >>](../07_Day_Class_Components/07_class_components.md)
|
||||
|
||||

|
||||
|
||||
- [Mapping arrays](#mapping-arrays)
|
||||
- [Mapping and rendering arrays](#mapping-and-rendering-arrays)
|
||||
- [Mapping array of numbers](#mapping-array-of-numbers)
|
||||
- [Mapping array of arrays](#mapping-array-of-arrays)
|
||||
- [Mapping array of objects](#mapping-array-of-objects)
|
||||
- [Key in mapping arrays](#key-in-mapping-arrays)
|
||||
- [Exercises](#exercises)
|
||||
- [Exercises: Level 1](#exercises-level-1)
|
||||
- [Exercises: Level 2](#exercises-level-2)
|
||||
- [Exercises: Level 3](#exercises-level-3)
|
||||
|
||||
# Mapping arrays
|
||||
|
||||
Array is the most frequently used data structure to handle many kind of problems. In React, we use map to modify an array to list of JSX by adding a certain HTML elements to each element of the array.
|
||||
|
||||
## Mapping and rendering arrays
|
||||
|
||||
Most of the time data is in the form of array or array of objects. To render this array or array of objects most of the time we modify the data using _map_. In the previous section, we have rendered the techs list using map. In this section also we will also see more examples.
|
||||
|
||||
In the following examples, you will see how we render a number array, a string array, a countries array and skills array on the browser.
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
const App = () => {
|
||||
return (
|
||||
<div className='container'>
|
||||
<div>
|
||||
<h1>Numbers List</h1>
|
||||
{[1, 2, 3, 4, 5]}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
If you check the browser, you will see the numbers are attached together in one line. To avoid this, we modify the array and change the array elements to JSX element. See the example below, the array has been modified to a list JSX elements.
|
||||
|
||||
### Mapping array of numbers
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const Numbers = ({ numbers }) => {
|
||||
// modifying array to array of li JSX
|
||||
const list = numbers.map((number) => <li>{number}</li>)
|
||||
return list
|
||||
}
|
||||
|
||||
// App component
|
||||
|
||||
const App = () => {
|
||||
const numbers = [1, 2, 3, 4, 5]
|
||||
|
||||
return (
|
||||
<div className='container'>
|
||||
<div>
|
||||
<h1>Numbers List</h1>
|
||||
<ul>
|
||||
<Numbers numbers={numbers} />
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
### Mapping array of arrays
|
||||
|
||||
Let's see how to map array of arrays
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const skills = [
|
||||
['HTML', 10],
|
||||
['CSS', 7],
|
||||
['JavaScript', 9],
|
||||
['React', 8],
|
||||
]
|
||||
|
||||
// Skill Component
|
||||
const Skill = ({ skill: [tech, level] }) => (
|
||||
<li>
|
||||
{tech} {level}
|
||||
</li>
|
||||
)
|
||||
|
||||
// Skills Component
|
||||
const Skills = ({ skills }) => {
|
||||
const skillsList = skills.map((skill) => <Skill skill={skill} />)
|
||||
console.log(skillsList)
|
||||
return <ul>{skillsList}</ul>
|
||||
}
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<div className='container'>
|
||||
<div>
|
||||
<h1>Skills Level</h1>
|
||||
<Skills skills={skills} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
### Mapping array of objects
|
||||
|
||||
Rendering array of objects
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const countries = [
|
||||
{ name: 'Finland', city: 'Helsinki' },
|
||||
{ name: 'Sweden', city: 'Stockholm' },
|
||||
{ name: 'Denmark', city: 'Copenhagen' },
|
||||
{ name: 'Norway', city: 'Oslo' },
|
||||
{ name: 'Iceland', city: 'Reykjavík' },
|
||||
]
|
||||
|
||||
// Country component
|
||||
const Country = ({ country: { name, city } }) => {
|
||||
return (
|
||||
<div>
|
||||
<h1>{name}</h1>
|
||||
<small>{city}</small>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// countries component
|
||||
const Countries = ({ countries }) => {
|
||||
const countryList = countries.map((country) => <Country country={country} />)
|
||||
return <div>{countryList}</div>
|
||||
}
|
||||
// App component
|
||||
const App = () => (
|
||||
<div className='container'>
|
||||
<div>
|
||||
<h1>Countries List</h1>
|
||||
<Countries countries={countries} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
### Key in mapping arrays
|
||||
|
||||
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity. Key should be unique. Mostly data has come with an id and we can use id as key. If we do not pass key react raise a warning on the browser. If the data does not have id we have to find a way to create a unique identifier for each elements when we map it. See the following example:
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const Numbers = ({ numbers }) => {
|
||||
// modifying array to array of li JSX
|
||||
const list = numbers.map((num) => <li key={num}>{num}</li>)
|
||||
return list
|
||||
}
|
||||
|
||||
const App = () => {
|
||||
const numbers = [1, 2, 3, 4, 5]
|
||||
|
||||
return (
|
||||
<div className='container'>
|
||||
<div>
|
||||
<h1>Numbers List</h1>
|
||||
<ul>
|
||||
<Numbers numbers={numbers} />
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
Let's also add in key in countries mapping example.
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const countries = [
|
||||
{ name: 'Finland', city: 'Helsinki' },
|
||||
{ name: 'Sweden', city: 'Stockholm' },
|
||||
{ name: 'Denmark', city: 'Copenhagen' },
|
||||
{ name: 'Norway', city: 'Oslo' },
|
||||
{ name: 'Iceland', city: 'Reykjavík' },
|
||||
]
|
||||
|
||||
// Country component
|
||||
const Country = ({ country: { name, city } }) => {
|
||||
return (
|
||||
<div>
|
||||
<h1>{name}</h1>
|
||||
<small>{city}</small>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// countries component
|
||||
const Countries = ({ countries }) => {
|
||||
const countryList = countries.map((country) => (
|
||||
<Country key={country.name} country={country} />
|
||||
))
|
||||
return <div>{countryList}</div>
|
||||
}
|
||||
const App = () => (
|
||||
<div className='container'>
|
||||
<div>
|
||||
<h1>Countries List</h1>
|
||||
<Countries countries={countries} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
# Exercises
|
||||
|
||||
## Exercises: Level 1
|
||||
|
||||
1. Why you need to map an array ?
|
||||
2. Why we need keys during mapping an array ?
|
||||
3. What is the importance of destructuring your code ?
|
||||
4. Does destructuring make your code clean and easy to read ?
|
||||
|
||||
## Exercises: Level 2
|
||||
|
||||
1. In the following design, evens are green, odds are yellow and prime numbers are red. Build the following colors using React component
|
||||
|
||||

|
||||
|
||||
2. Create the following hexadecimal colors using React component
|
||||
|
||||

|
||||
|
||||
## Exercises: Level 3
|
||||
|
||||
1.Make the following bar group using given [data](../06_Day_Map_List_Keys/06_map_list_keys_boilerplate/src/data/ten_most_highest_populations.js)
|
||||
|
||||

|
||||
|
||||
🎉 CONGRATULATIONS ! 🎉
|
||||
|
||||
[<< Day 5](./../05_Day_Props/05_props.md) | [Day 7 >>](../07_Day_Class_Components/07_class_components.md)
|
@ -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 3
|
||||
|
||||
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 },
|
||||
]
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,49 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
|
||||
// importing data
|
||||
|
||||
import { countriesData } from './data/countries'
|
||||
import { tenMostHighestPopulations } from './data/ten_most_highest_populations'
|
||||
|
||||
const countries = [
|
||||
{ name: 'Finland', city: 'Helsinki' },
|
||||
{ name: 'Sweden', city: 'Stockholm' },
|
||||
{ name: 'Denmark', city: 'Copenhagen' },
|
||||
{ name: 'Norway', city: 'Oslo' },
|
||||
{ name: 'Iceland', city: 'Reykjavík' },
|
||||
]
|
||||
|
||||
// Country component
|
||||
const Country = ({ country: { name, city } }) => {
|
||||
return (
|
||||
<div>
|
||||
<h1>{name}</h1>
|
||||
<small>{city}</small>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// countries component
|
||||
const Countries = ({ countries }) => {
|
||||
const countryList = countries.map((country) => (
|
||||
<Country key={country.name} country={country} />
|
||||
))
|
||||
return <div>{countryList}</div>
|
||||
}
|
||||
|
||||
// The App, or the parent or the container component
|
||||
// Functional Component
|
||||
const App = () => {
|
||||
return (
|
||||
<div className='app'>
|
||||
<div>
|
||||
<h1>Countries List</h1>
|
||||
<Countries countries={countries} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
@ -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 3
|
||||
|
||||
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 },
|
||||
]
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,194 @@
|
||||
// index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import asabenehImage from './images/asabeneh.jpg'
|
||||
|
||||
// Fuction to show month date year
|
||||
|
||||
// User Card Component
|
||||
const UserCard = ({ user: { firstName, lastName, image } }) => (
|
||||
<div className='user-card'>
|
||||
<img src={image} alt={firstName} />
|
||||
<h2>
|
||||
{firstName}
|
||||
{lastName}
|
||||
</h2>
|
||||
</div>
|
||||
)
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 18,
|
||||
color: 'white',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const { techs } = this.props
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={this.props.techs} />
|
||||
</ul>
|
||||
<UserCard user={this.props.user} />
|
||||
<Button
|
||||
text='Greet People'
|
||||
onClick={this.props.greetPeople}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
<Button
|
||||
text='Show Time'
|
||||
onClick={this.props.handleTime}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {this.props.date.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return ` ${month} ${date}, ${year}`
|
||||
}
|
||||
handleTime = () => {
|
||||
alert(this.showDate(new Date()))
|
||||
}
|
||||
greetPeople = () => {
|
||||
alert('Welcome to 30 Days Of React Challenge, 2020')
|
||||
}
|
||||
render() {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 7, 2020',
|
||||
}
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
|
||||
// copying the author from data object to user variable using spread operator
|
||||
const user = { ...data.author, image: asabenehImage }
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
<Main
|
||||
user={user}
|
||||
techs={techs}
|
||||
handleTime={this.handleTime}
|
||||
greetPeople={this.greetPeople}
|
||||
/>
|
||||
|
||||
<Footer date={new Date()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
|
@ -0,0 +1,838 @@
|
||||
<div align="center">
|
||||
<h1> 30 Days Of React: Class Components </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 6](../06_Day_Map_List_Keys/06_map_list_keys.md) | [Day 8 >>](../07_Day_Class_Components/07_class_components.md)
|
||||
|
||||

|
||||
|
||||
- [Class Components](#class-components)
|
||||
- [Accessing props in Class components](#accessing-props-in-class-components)
|
||||
- [Methods in Class based component](#methods-in-class-based-component)
|
||||
- [Exercises](#exercises)
|
||||
- [Exercises: Level 1](#exercises-level-1)
|
||||
- [Exercises: Level 2](#exercises-level-2)
|
||||
|
||||
# Class Components
|
||||
|
||||
In the previous sections, we have covered JSX, functional component and props. In this section, we will cover class components or statefull component. Only class based components used to have state and life cycle methods. However, after React version 16.8.0 functional components can have state and life cycle using React Hooks. In 30 Days Of React challenge, we will cover React before 16.8.0 and after, that mean both old and newest version. There are lots of codes written in older version and at some point it may need migration. In addition, to understand React very well someone has to understand class based component too.
|
||||
|
||||
All the previous components are functional components. Let us make also class based component. Class based component is made using JavaScript class and it inherits from react Component. Let us learn how to make a class based component by converting all the functional components we made previously. It is not important to convert all but we are converting them for the sake of learning how to change functional components to class components.
|
||||
|
||||
```js
|
||||
// Pure JavaScript class and child
|
||||
// Imagine this what we import from React package
|
||||
class Component {
|
||||
constructor(props) {}
|
||||
}
|
||||
|
||||
// This how we make class based components by inheriting from the parent
|
||||
class Child extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Functional React component
|
||||
|
||||
```js
|
||||
// index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
// Header Component
|
||||
// Functional component
|
||||
const Header = () => (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
<h2>Getting Started React</h2>
|
||||
<h3>JavaScript Library</h3>
|
||||
<p>Asabeneh Yetayeh</p>
|
||||
<small>Oct 6, 2020</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<Header />, rootElement)
|
||||
```
|
||||
|
||||
Class based React component is a child of React.Component and it has a built-in render method and it may have a constructor.
|
||||
|
||||
```js
|
||||
//index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
<h2>Getting Started React</h2>
|
||||
<h3>JavaScript Library</h3>
|
||||
<p>Asabeneh Yetayeh</p>
|
||||
<small>Oct 7, 2020</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<Header />, rootElement)
|
||||
```
|
||||
|
||||
Let's see the above component with a constructor
|
||||
|
||||
```js
|
||||
//index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class base component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
<h2>Getting Started React</h2>
|
||||
<h3>JavaScript Library</h3>
|
||||
<p>Asabeneh Yetayeh</p>
|
||||
<small>Oct 7, 2020</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<Header />, rootElement)
|
||||
```
|
||||
|
||||
Let's change all the functional component to class based components
|
||||
|
||||
```js
|
||||
// TechList Component
|
||||
// functional component
|
||||
const TechList = () => {
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Functional Component
|
||||
const Main = () => (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList />
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList />
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Functional component
|
||||
const Footer = () => (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright 2020</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright 2020</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// The App, or the parent or the container component
|
||||
// Functional Component
|
||||
const App = () => (
|
||||
<div className='app'>
|
||||
<Header />
|
||||
<Main />
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
|
||||
// The App, or the parent or the container component
|
||||
// Class Component
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header />
|
||||
<Main />
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Let's put all the class based components together in one file.
|
||||
|
||||
```js
|
||||
//index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class base component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
<h2>Getting Started React</h2>
|
||||
<h3>JavaScript Library</h3>
|
||||
<p>Asabeneh Yetayeh</p>
|
||||
<small>Oct 7, 2020</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList />
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright 2020</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// The App, or the parent or the container component
|
||||
// Class Component
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header />
|
||||
<Main />
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
## Accessing props in Class components
|
||||
|
||||
We stated that props is a means to send data from on component to another or we can call it that props is a data carrier. Therefore, we should handle props in class based component too. We can access props of a class based component using the keyword _this_. See the example below.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{this.props.data.welcome}</h1>
|
||||
<h2>{this.props.data.title}</h2>
|
||||
<h3>
|
||||
{this.props.data.author.firstName} {this.props.data.author.lastName}
|
||||
</h3>
|
||||
<small>{this.props.data.date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
const App = () => {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 7, 2020',
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
As you can see in the above example, to get the data out from props we have write _props.data_ every time. We can avoid this repetition using destructuring.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
const App = () => {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 6, 2020',
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
As you can see, the above code cleaner than the previous. Now, let's clean all the components we have and put all together.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const { techs } = this.props
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={this.props.techs} />
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {this.props.date.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
render() {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 7, 2020',
|
||||
}
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
<Main techs={techs} />
|
||||
<Footer date={new Date()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
## Methods in Class based component
|
||||
|
||||
We access methods in class based component. Most of the time, we write different methods on the parent component and we pass them to child components. Let's see the implementation.
|
||||
|
||||
Let's add a method on this component.
|
||||
|
||||
```js
|
||||
//index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
greetPeople = () => {
|
||||
alert('Welcome to 30 Days Of React Challenge, 2020')
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
<h2>Getting Started React</h2>
|
||||
<h3>JavaScript Library</h3>
|
||||
<p>Asabeneh Yetayeh</p>
|
||||
<small>Oct 7, 2020</small>
|
||||
<button onClick={this.greetPeople}> Greet </button>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<Header />, rootElement)
|
||||
```
|
||||
|
||||
The invoking or calling of the method triggers when the event occurs. Therefore, whenever you pass a method to an event listener do not invoke the method.
|
||||
|
||||
Now, let's the code we had add all the necessary methods.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import asabenehImage from './images/asabeneh.jpg'
|
||||
|
||||
// Fuction to show month date year
|
||||
|
||||
// User Card Component
|
||||
const UserCard = ({ user: { firstName, lastName, image } }) => (
|
||||
<div className='user-card'>
|
||||
<img src={image} alt={firstName} />
|
||||
<h2>
|
||||
{firstName}
|
||||
{lastName}
|
||||
</h2>
|
||||
</div>
|
||||
)
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 18,
|
||||
color: 'white',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const { techs } = this.props
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={this.props.techs} />
|
||||
</ul>
|
||||
<UserCard user={this.props.user} />
|
||||
<Button
|
||||
text='Greet People'
|
||||
onClick={this.props.greetPeople}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
<Button
|
||||
text='Show Time'
|
||||
onClick={this.props.handleTime}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {this.props.date.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return ` ${month} ${date}, ${year}`
|
||||
}
|
||||
handleTime = () => {
|
||||
alert(this.showDate(new Date()))
|
||||
}
|
||||
greetPeople = () => {
|
||||
alert('Welcome to 30 Days Of React Challenge, 2020')
|
||||
}
|
||||
render() {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 7, 2020',
|
||||
}
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
|
||||
// copying the author from data object to user variable using spread operator
|
||||
const user = { ...data.author, image: asabenehImage }
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
<Main
|
||||
user={user}
|
||||
techs={techs}
|
||||
handleTime={this.handleTime}
|
||||
greetPeople={this.greetPeople}
|
||||
/>
|
||||
|
||||
<Footer date={new Date()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
Most of the time the container or the parent component can be written as class component and others as functional or presentational components. Data usually flows from parent components to child component and it is unidirectional. However, the latest version of react can allow us to write every component in our application only with functional components. This was impossible in previous versions.
|
||||
In next section, we will cover state which is the heart of React. State allows React component to rerender when whenever there is a change in state.
|
||||
|
||||
# Exercises
|
||||
|
||||
## Exercises: Level 1
|
||||
|
||||
1. How do you write a pure JavaScript function
|
||||
2. What is inheritance and how do you make a child from a parent class?
|
||||
3. What is class based React component ?
|
||||
4. What is the difference between functional React component and class based React component ?
|
||||
5. What is the use cases of class based component ?
|
||||
6. What is React life cycle ? (not covered yet) ?
|
||||
7. What is state in React ?
|
||||
|
||||
## Exercises: Level 2
|
||||
|
||||
Learn more about class based component by changing previous days exercises to class based components
|
||||
|
||||
🎉 CONGRATULATIONS ! 🎉
|
||||
|
||||
[<< Day 6](../06_Day_Map_List_Keys/06_map_list_keys.md) | [Day 8 >>](../07_Day_Class_Components/07_class_components.md)
|
@ -0,0 +1,513 @@
|
||||
<div align="center">
|
||||
<h1> 30 Days Of React: Statet</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 7](../07_Day_Class_Components/07_class_components.md) | [Day 9 >>](../09_Day_Conditional_Rendering/09_conditional_rendering.md)
|
||||
|
||||

|
||||
|
||||
- [State](#state)
|
||||
- [What is State?](#what-is-state)
|
||||
- [How to set a state](#how-to-set-a-state)
|
||||
- [Resetting a state using a JavaScript method](#resetting-a-state-using-a-javascript-method)
|
||||
- [Exercises](#exercises)
|
||||
- [Exercises: Level 1](#exercises-level-1)
|
||||
- [Exercises: Level 2](#exercises-level-2)
|
||||
- [Exercises: Level 3](#exercises-level-3)
|
||||
|
||||
# State
|
||||
|
||||
## What is State?
|
||||
|
||||
What is state ? The English meaning of state is _the particular condition that someone or something is in at a specific time_.
|
||||
|
||||
Let us see some states being something - Are you happy or sad? - Is light on or off ? Is present or absent ? - Is full or empty ? For instance, I am happy because I am enjoying creating 30 Days Of React challenge. I believe that you are happy too.
|
||||
|
||||
State is an object in react which let the component re-render when state data changes.
|
||||
|
||||
## How to set a state
|
||||
|
||||
We set an initial state inside the constructor or outside the constructor of a class based component. We do not directly change or mutate the state but we use the _setState()_ method to reset to a new state. . As you can see below in the state object we have count with initial value 0. We can access the state object using _this.state_ and the property name. See the example below.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
class App extends React.Component {
|
||||
// declaring state
|
||||
state = {
|
||||
count: 0,
|
||||
}
|
||||
render() {
|
||||
// accessing the state value
|
||||
const count = this.state.count
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1>{count} </h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
If you run the above code you will see zero on the browser. We can increase or decrease the value the state by changing the value of the state using JavaScript method.
|
||||
|
||||
## Resetting a state using a JavaScript method
|
||||
|
||||
Now, let's add some methods which increase or decrease the value of count by clicking a button. Let us add a button to increase and a button to decrease the value of count. To set the state we use react method _this.setState_. See the example below
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
class App extends React.Component {
|
||||
// declaring state
|
||||
state = {
|
||||
count: 0,
|
||||
}
|
||||
render() {
|
||||
// accessing the state value
|
||||
const count = this.state.count
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1>{count} </h1>
|
||||
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
|
||||
Add One
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
If you understand the above example, adding minus one method will be easy. Let us add the minus one method on the click event.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
class App extends React.Component {
|
||||
// declaring state
|
||||
state = {
|
||||
count: 0,
|
||||
}
|
||||
render() {
|
||||
// accessing the state value
|
||||
const count = this.state.count
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1>{count} </h1>
|
||||
|
||||
<div>
|
||||
<button
|
||||
onClick={() => this.setState({ count: this.state.count + 1 })}
|
||||
>
|
||||
Add One
|
||||
</button>{' '}
|
||||
<button
|
||||
onClick={() => this.setState({ count: this.state.count - 1 })}
|
||||
>
|
||||
Minus One
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
Both button work well, but we need to re-structure the code well. Let us create separate methods in the component.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
class App extends React.Component {
|
||||
// declaring state
|
||||
state = {
|
||||
count: 0,
|
||||
}
|
||||
// method which add one to the state
|
||||
|
||||
addOne = () => {
|
||||
this.setState({ count: this.state.count + 1 })
|
||||
}
|
||||
|
||||
// method which subtract one to the state
|
||||
minusOne = () => {
|
||||
this.setState({ count: this.state.count - 1 })
|
||||
}
|
||||
render() {
|
||||
// accessing the state value
|
||||
const count = this.state.count
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1>{count} </h1>
|
||||
|
||||
<div>
|
||||
<button className='btn btn-add' onClick={this.addOne}>
|
||||
+1
|
||||
</button>{' '}
|
||||
<button className='btn btn-minus' onClick={this.minusOne}>
|
||||
-1
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
Let us do more example about state, in the following example we will develop small application which shows either a dog or cat.
|
||||
We can start by setting the initial state with cat then when it is clicked it will show dog and alternatively. We need one method which changes the animal alternatively. See the code below. If you want to see live click [here](https://codepen.io/Asabeneh/full/LYVxKpq).
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
class App extends React.Component {
|
||||
// declaring state
|
||||
state = {
|
||||
image: 'https://www.smithsstationah.com/imagebank/eVetSites/Feline/01.jpg',
|
||||
}
|
||||
changeAnimal = () => {
|
||||
let dogURL =
|
||||
'https://static.onecms.io/wp-content/uploads/sites/12/2015/04/dogs-pembroke-welsh-corgi-400x400.jpg'
|
||||
let catURL =
|
||||
'https://www.smithsstationah.com/imagebank/eVetSites/Feline/01.jpg'
|
||||
let image = this.state.image === catURL ? dogURL : catURL
|
||||
this.setState({ image })
|
||||
}
|
||||
|
||||
render() {
|
||||
// accessing the state value
|
||||
const count = this.state.count
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1>30 Days Of React</h1>
|
||||
<div className='animal'>
|
||||
<img src={this.state.image} alt='animal' />
|
||||
</div>
|
||||
|
||||
<button onClick={this.changeAnimal} class='btn btn-add'>
|
||||
Change
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
Now, let's put all the codes we have so far and also let's implement state when it is necessary.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import asabenehImage from './images/asabeneh.jpg'
|
||||
|
||||
// Fuction to show month date year
|
||||
|
||||
const showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return ` ${month} ${date}, ${year}`
|
||||
}
|
||||
|
||||
// User Card Component
|
||||
const UserCard = ({ user: { firstName, lastName, image } }) => (
|
||||
<div className='user-card'>
|
||||
<img src={image} alt={firstName} />
|
||||
<h2>
|
||||
{firstName}
|
||||
{lastName}
|
||||
</h2>
|
||||
</div>
|
||||
)
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 18,
|
||||
color: 'white',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header style={this.props.styles}>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Count = ({ count, addOne, minusOne }) => (
|
||||
<div>
|
||||
<h1>{count} </h1>
|
||||
<div>
|
||||
<Button text='+1' onClick={addOne} style={buttonStyles} />
|
||||
<Button text='-1' onClick={minusOne} style={buttonStyles} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const { techs } = this.props
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
techs,
|
||||
user,
|
||||
greetPeople,
|
||||
handleTime,
|
||||
changeBackground,
|
||||
count,
|
||||
addOne,
|
||||
minusOne,
|
||||
} = this.props
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={techs} />
|
||||
</ul>
|
||||
<UserCard user={user} />
|
||||
<Button
|
||||
text='Greet People'
|
||||
onClick={greetPeople}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
<Button text='Show Time' onClick={handleTime} style={buttonStyles} />
|
||||
<Button
|
||||
text='Change Background'
|
||||
onClick={changeBackground}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
<Count count={count} addOne={addOne} minusOne={minusOne} />
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {this.props.date.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
count: 0,
|
||||
styles: {
|
||||
backgroundColor: '',
|
||||
color: '',
|
||||
},
|
||||
}
|
||||
showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return ` ${month} ${date}, ${year}`
|
||||
}
|
||||
addOne = () => {
|
||||
this.setState({ count: this.state.count + 1 })
|
||||
}
|
||||
|
||||
// method which subtract one to the state
|
||||
minusOne = () => {
|
||||
this.setState({ count: this.state.count - 1 })
|
||||
}
|
||||
handleTime = () => {
|
||||
alert(this.showDate(new Date()))
|
||||
}
|
||||
greetPeople = () => {
|
||||
alert('Welcome to 30 Days Of React Challenge, 2020')
|
||||
}
|
||||
changeBackground = () => {}
|
||||
render() {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 7, 2020',
|
||||
}
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
const date = new Date()
|
||||
// copying the author from data object to user variable using spread operator
|
||||
const user = { ...data.author, image: asabenehImage }
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
{this.state.backgroundColor}
|
||||
<Header data={data} />
|
||||
<Main
|
||||
user={user}
|
||||
techs={techs}
|
||||
handleTime={this.handleTime}
|
||||
greetPeople={this.greetPeople}
|
||||
changeBackground={this.changeBackground}
|
||||
addOne={this.addOne}
|
||||
minusOne={this.minusOne}
|
||||
count={this.state.count}
|
||||
/>
|
||||
<Footer date={new Date()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
I believe that now you have a very good understanding of state. After this, we will use state in other sections too because state and props is the core of a react application.
|
||||
|
||||
## Exercises
|
||||
|
||||
### Exercises: Level 1
|
||||
|
||||
1. What was your state today? Are you happy? I hope so. If you manage to make it this far you should be happy.
|
||||
2. What is state in React ?
|
||||
3. What is the difference between props and state in React ?
|
||||
4. How do you access state in a React component ?
|
||||
5. How do you set a set in a React component ?
|
||||
|
||||
### Exercises: Level 2
|
||||
|
||||
1. Use React state to change the background of the page. You can use this technique to apply a dark mode for your portfolio.
|
||||
|
||||

|
||||
|
||||
2. After long time of lock down you may think of travelling and you do not know where to go. Then make use of this random country selector to select your holiday destination.
|
||||
|
||||

|
||||
|
||||
### Exercises: Level 3
|
||||
|
||||
Coming
|
||||
|
||||
🎉 CONGRATULATIONS ! 🎉
|
||||
|
||||
[<< Day 7](../07_Day_Class_Components/07_class_components.md) | [Day 9 >>](../09_Day_Conditional_Rendering/09_conditional_rendering.md)
|
@ -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 3
|
||||
|
||||
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 },
|
||||
]
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,256 @@
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import asabenehImage from './images/asabeneh.jpg'
|
||||
|
||||
// Fuction to show month date year
|
||||
|
||||
const showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return ` ${month} ${date}, ${year}`
|
||||
}
|
||||
|
||||
// User Card Component
|
||||
const UserCard = ({ user: { firstName, lastName, image } }) => (
|
||||
<div className='user-card'>
|
||||
<img src={image} alt={firstName} />
|
||||
<h2>
|
||||
{firstName}
|
||||
{lastName}
|
||||
</h2>
|
||||
</div>
|
||||
)
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 18,
|
||||
color: 'white',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// the code inside the constructor run before any other code
|
||||
}
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header style={this.props.styles}>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Count = ({ count, addOne, minusOne }) => (
|
||||
<div>
|
||||
<h1>{count} </h1>
|
||||
<div>
|
||||
<Button text='+1' onClick={addOne} style={buttonStyles} />
|
||||
<Button text='-1' onClick={minusOne} style={buttonStyles} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const { techs } = this.props
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
techs,
|
||||
user,
|
||||
greetPeople,
|
||||
handleTime,
|
||||
changeBackground,
|
||||
count,
|
||||
addOne,
|
||||
minusOne,
|
||||
} = this.props
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={techs} />
|
||||
</ul>
|
||||
<UserCard user={user} />
|
||||
<Button
|
||||
text='Greet People'
|
||||
onClick={greetPeople}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
<Button text='Show Time' onClick={handleTime} style={buttonStyles} />
|
||||
<Button
|
||||
text='Change Background'
|
||||
onClick={changeBackground}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
<Count count={count} addOne={addOne} minusOne={minusOne} />
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {this.props.date.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
count: 0,
|
||||
styles: {
|
||||
backgroundColor: '',
|
||||
color: '',
|
||||
},
|
||||
}
|
||||
showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return ` ${month} ${date}, ${year}`
|
||||
}
|
||||
addOne = () => {
|
||||
this.setState({ count: this.state.count + 1 })
|
||||
}
|
||||
|
||||
// method which subtract one to the state
|
||||
minusOne = () => {
|
||||
this.setState({ count: this.state.count - 1 })
|
||||
}
|
||||
handleTime = () => {
|
||||
alert(this.showDate(new Date()))
|
||||
}
|
||||
greetPeople = () => {
|
||||
alert('Welcome to 30 Days Of React Challenge, 2020')
|
||||
}
|
||||
changeBackground = () => {}
|
||||
render() {
|
||||
const data = {
|
||||
welcome: 'Welcome to 30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 7, 2020',
|
||||
}
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
const date = new Date()
|
||||
// copying the author from data object to user variable using spread operator
|
||||
const user = { ...data.author, image: asabenehImage }
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
{this.state.backgroundColor}
|
||||
<Header data={data} />
|
||||
<Main
|
||||
user={user}
|
||||
techs={techs}
|
||||
handleTime={this.handleTime}
|
||||
greetPeople={this.greetPeople}
|
||||
changeBackground={this.changeBackground}
|
||||
addOne={this.addOne}
|
||||
minusOne={this.minusOne}
|
||||
count={this.state.count}
|
||||
/>
|
||||
<Footer date={new Date()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
@ -0,0 +1,785 @@
|
||||
<div align="center">
|
||||
<h1> 30 Days Of React: Conditional Rendering</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 8](../08_Day_States/08_states.md) | [Day 10 >>](../10_Day_Events/10_events.md)
|
||||
|
||||

|
||||
|
||||
# Conditional Rendering
|
||||
|
||||
As we can understand from the term, conditional rendering is a way to render different JSX or component at different condition. We can implement conditional rendering using regular if and else statement, ternary operator and &&. Let's implement a different conditional rendering.
|
||||
|
||||
## Conditional Rendering using If and Else statement
|
||||
|
||||
In the code below, we have an initial state of loggedIn which is false. If the state is false we inform user to log in otherwise we welcome the user.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
<p>Select a country for your next holiday</p>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
loggedIn: false,
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
welcome: '30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 9, 2020',
|
||||
}
|
||||
|
||||
// conditional rendering using if and else statement
|
||||
|
||||
let status
|
||||
|
||||
if (this.state.loggedIn) {
|
||||
status = <h3>Welcome to 30 Days Of React</h3>
|
||||
} else {
|
||||
status = <h3>Please Login</h3>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
{status}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
Let's add a method which allow as to toggle the status of the user. We should have a button to handle event for logging in and logging out.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 22,
|
||||
color: 'white',
|
||||
margin: '0 auto',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
loggedIn: false,
|
||||
}
|
||||
handleLogin = () => {
|
||||
this.setState({
|
||||
loggedIn: !this.state.loggedIn,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
welcome: '30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 9, 2020',
|
||||
}
|
||||
|
||||
let status
|
||||
let text
|
||||
|
||||
if (this.state.loggedIn) {
|
||||
status = <h1>Welcome to 30 Days Of React</h1>
|
||||
text = 'Logout'
|
||||
} else {
|
||||
status = <h3>Please Login</h3>
|
||||
text = 'Login'
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
{status}
|
||||
<Button text={text} style={buttonStyles} onClick={this.handleLogin} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
How about if our condition is more than two? Like pure JavaScript we can use if else if statement. In general, conditional rendering is not different from pure JavaScript conditional statement.
|
||||
|
||||
## Conditional Rendering using Ternary Operator
|
||||
|
||||
Ternary operator is an an alternative for if else statement. However, there is more use cases for ternary operator than if else statement. For example, use can use ternary operator inside styles, className or many places in a component than regular if else statement.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 22,
|
||||
color: 'white',
|
||||
margin: '0 auto',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
loggedIn: false,
|
||||
}
|
||||
handleLogin = () => {
|
||||
this.setState({
|
||||
loggedIn: !this.state.loggedIn,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
welcome: '30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 9, 2020',
|
||||
}
|
||||
|
||||
let status = this.state.loggedIn ? (
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
) : (
|
||||
<h3>Please Login</h3>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
{status}
|
||||
<Button
|
||||
text={this.state.loggedIn ? 'Logout' : 'Login'}
|
||||
style={buttonStyles}
|
||||
onClick={this.handleLogin}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
In addition to JSX, we can also conditionally render a component. Let's change the above conditional JSX to a component.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 22,
|
||||
color: 'white',
|
||||
margin: '0 auto',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Login = () => (
|
||||
<div>
|
||||
<h3>Please Login</h3>
|
||||
</div>
|
||||
)
|
||||
const Welcome = (props) => (
|
||||
<div>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
</div>
|
||||
)
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
loggedIn: false,
|
||||
}
|
||||
handleLogin = () => {
|
||||
this.setState({
|
||||
loggedIn: !this.state.loggedIn,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
welcome: '30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 9, 2020',
|
||||
}
|
||||
|
||||
const status = this.state.loggedIn ? <Welcome /> : <Login />
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
{status}
|
||||
<Button
|
||||
text={this.state.loggedIn ? 'Logout' : 'Login'}
|
||||
style={buttonStyles}
|
||||
onClick={this.handleLogin}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
## Conditional Rendering using && Operator
|
||||
|
||||
The && operator render the right JSX operand if the left operand(expression) is true.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 22,
|
||||
color: 'white',
|
||||
margin: '0 auto',
|
||||
}
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header style={this.props.styles}>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
const Login = () => (
|
||||
<div>
|
||||
<h3>Please Login</h3>
|
||||
</div>
|
||||
)
|
||||
const Welcome = (props) => (
|
||||
<div>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
</div>
|
||||
)
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
loggedIn: false,
|
||||
techs: ['HTML', 'CSS', 'JS'],
|
||||
}
|
||||
handleLogin = () => {
|
||||
this.setState({
|
||||
loggedIn: !this.state.loggedIn,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
welcome: '30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 9, 2020',
|
||||
}
|
||||
|
||||
// We can destructure state
|
||||
|
||||
const { loggedIn, techs } = this.state
|
||||
|
||||
const status = loggedIn ? <Welcome /> : <Login />
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
{status}
|
||||
<Button
|
||||
text={loggedIn ? 'Logout' : 'Login'}
|
||||
style={buttonStyles}
|
||||
onClick={this.handleLogin}
|
||||
/>
|
||||
{techs.length === 3 && (
|
||||
<p>You have all the prerequisite courses to get started React</p>
|
||||
)}
|
||||
{!loggedIn && (
|
||||
<p>
|
||||
Please login to access more information about 30 Days Of React
|
||||
challenge
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
In the previous section, we used alert box to greet people and also to display time. Let's render the greeting and time on browser DOM instead of displaying on alert box.
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
console.log(this.props.data)
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header style={this.props.styles}>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Message = ({ message }) => (
|
||||
<div>
|
||||
<h1>{message}</h1>
|
||||
</div>
|
||||
)
|
||||
const Login = () => (
|
||||
<div>
|
||||
<h3>Please Login</h3>
|
||||
</div>
|
||||
)
|
||||
const Welcome = (props) => (
|
||||
<div>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
</div>
|
||||
)
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
render() {
|
||||
const { techs } = this.props
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
techs,
|
||||
greetPeople,
|
||||
handleTime,
|
||||
loggedIn,
|
||||
handleLogin,
|
||||
message,
|
||||
} = this.props
|
||||
console.log(message)
|
||||
|
||||
const status = loggedIn ? <Welcome /> : <Login />
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={this.props.techs} />
|
||||
</ul>
|
||||
{techs.length === 3 && (
|
||||
<p>You have all the prerequisite courses to get started React</p>
|
||||
)}
|
||||
<div>
|
||||
<Button
|
||||
text='Show Time'
|
||||
onClick={handleTime}
|
||||
style={buttonStyles}
|
||||
/>{' '}
|
||||
<Button
|
||||
text='Greet People'
|
||||
onClick={greetPeople}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
{!loggedIn && <p>Please login to access more information about 30 Days Of React challenge</p>}
|
||||
</div>
|
||||
<div style={{ margin: 30 }}>
|
||||
<Button
|
||||
text={loggedIn ? 'Logout' : 'Login'}
|
||||
style={buttonStyles}
|
||||
onClick={handleLogin}
|
||||
/>
|
||||
<br />
|
||||
{status}
|
||||
</div>
|
||||
<Message message={message} />
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 22,
|
||||
color: 'white',
|
||||
margin: '0 auto',
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {this.props.date.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
loggedIn: false,
|
||||
techs: ['HTML', 'CSS', 'JS'],
|
||||
message: 'Click show time or Greet people to change me',
|
||||
}
|
||||
handleLogin = () => {
|
||||
this.setState({
|
||||
loggedIn: !this.state.loggedIn,
|
||||
})
|
||||
}
|
||||
showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return `${month} ${date}, ${year}`
|
||||
}
|
||||
handleTime = () => {
|
||||
let message = this.showDate(new Date())
|
||||
this.setState({ message })
|
||||
}
|
||||
greetPeople = () => {
|
||||
let message = 'Welcome to 30 Days Of React Challenge, 2020'
|
||||
this.setState({ message })
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
welcome: '30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 9, 2020',
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
|
||||
<Main
|
||||
techs={techs}
|
||||
handleTime={this.handleTime}
|
||||
greetPeople={this.greetPeople}
|
||||
loggedIn={this.state.loggedIn}
|
||||
handleLogin={this.handleLogin}
|
||||
message={this.state.message}
|
||||
/>
|
||||
|
||||
<Footer date={new Date()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
## Exercises
|
||||
|
||||
### Exercises: Level 1
|
||||
|
||||
1. What is conditional rendering?
|
||||
2. How do you implement conditional rendering?
|
||||
3. Which method of conditional rendering do you prefer?
|
||||
|
||||
### Exercises: Level 2
|
||||
|
||||
1. Make a single page application which changes the body of the background based on the time of the day(Autumn, Winter, Spring, Summer)
|
||||
2. Make a single page application which change the body of the background based on the time of the day(Morning, Noon, Evening, Night)
|
||||
|
||||
### Exercises: Level 3
|
||||
|
||||
Coming
|
||||
|
||||
🎉 CONGRATULATIONS ! 🎉
|
||||
|
||||
[<< Day 8](../08_Day_States/08_states.md) | [Day 10 >>](../10_Day_Events/10_events.md)
|
@ -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 3
|
||||
|
||||
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 },
|
||||
]
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,228 @@
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// class based component
|
||||
class Header extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
welcome,
|
||||
title,
|
||||
subtitle,
|
||||
author: { firstName, lastName },
|
||||
date,
|
||||
} = this.props.data
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div className='header-wrapper'>
|
||||
<h1>{welcome}</h1>
|
||||
<h2>{title}</h2>
|
||||
<h3>{subtitle}</h3>
|
||||
<p>
|
||||
{firstName} {lastName}
|
||||
</p>
|
||||
<small>{date}</small>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Message = ({ message }) => (
|
||||
<div>
|
||||
<h1>{message}</h1>
|
||||
</div>
|
||||
)
|
||||
const Login = () => (
|
||||
<div>
|
||||
<h3>Please Login</h3>
|
||||
</div>
|
||||
)
|
||||
const Welcome = (props) => (
|
||||
<div>
|
||||
<h1>Welcome to 30 Days Of React</h1>
|
||||
</div>
|
||||
)
|
||||
|
||||
// A button component
|
||||
const Button = ({ text, onClick, style }) => (
|
||||
<button style={style} onClick={onClick}>
|
||||
{text}
|
||||
</button>
|
||||
)
|
||||
|
||||
// TechList Component
|
||||
// class base component
|
||||
class TechList extends React.Component {
|
||||
render() {
|
||||
const { techs } = this.props
|
||||
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>)
|
||||
return techsFormatted
|
||||
}
|
||||
}
|
||||
|
||||
// Main Component
|
||||
// Class Component
|
||||
class Main extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
techs,
|
||||
greetPeople,
|
||||
handleTime,
|
||||
loggedIn,
|
||||
handleLogin,
|
||||
message,
|
||||
} = this.props
|
||||
console.log(message)
|
||||
|
||||
const status = loggedIn ? <Welcome /> : <Login />
|
||||
return (
|
||||
<main>
|
||||
<div className='main-wrapper'>
|
||||
<p>Prerequisite to get started react.js:</p>
|
||||
<ul>
|
||||
<TechList techs={this.props.techs} />
|
||||
</ul>
|
||||
{techs.length === 3 && (
|
||||
<p>You have all the prerequisite courses to get started React</p>
|
||||
)}
|
||||
<div>
|
||||
<Button
|
||||
text='Show Time'
|
||||
onClick={handleTime}
|
||||
style={buttonStyles}
|
||||
/>{' '}
|
||||
<Button
|
||||
text='Greet People'
|
||||
onClick={greetPeople}
|
||||
style={buttonStyles}
|
||||
/>
|
||||
{!loggedIn && (
|
||||
<p>
|
||||
Please login to access more information about 30 Days Of React
|
||||
challenge
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ margin: 30 }}>
|
||||
<Button
|
||||
text={loggedIn ? 'Logout' : 'Login'}
|
||||
style={buttonStyles}
|
||||
onClick={handleLogin}
|
||||
/>
|
||||
<br />
|
||||
{status}
|
||||
</div>
|
||||
<Message message={message} />
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// CSS styles in JavaScript Object
|
||||
const buttonStyles = {
|
||||
backgroundColor: '#61dbfb',
|
||||
padding: 10,
|
||||
border: 'none',
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
cursor: 'pointer',
|
||||
fontSize: 22,
|
||||
color: 'white',
|
||||
margin: '0 auto',
|
||||
}
|
||||
|
||||
// Footer Component
|
||||
// Class component
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className='footer-wrapper'>
|
||||
<p>Copyright {this.props.date.getFullYear()}</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
loggedIn: false,
|
||||
techs: ['HTML', 'CSS', 'JS'],
|
||||
message: 'Click show time or Greet people to change me',
|
||||
}
|
||||
handleLogin = () => {
|
||||
this.setState({
|
||||
loggedIn: !this.state.loggedIn,
|
||||
})
|
||||
}
|
||||
showDate = (time) => {
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
]
|
||||
|
||||
const month = months[time.getMonth()].slice(0, 3)
|
||||
const year = time.getFullYear()
|
||||
const date = time.getDate()
|
||||
return `${month} ${date}, ${year}`
|
||||
}
|
||||
handleTime = () => {
|
||||
let message = this.showDate(new Date())
|
||||
this.setState({ message })
|
||||
}
|
||||
greetPeople = () => {
|
||||
let message = 'Welcome to 30 Days Of React Challenge, 2020'
|
||||
this.setState({ message })
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
welcome: '30 Days Of React',
|
||||
title: 'Getting Started React',
|
||||
subtitle: 'JavaScript Library',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
date: 'Oct 9, 2020',
|
||||
}
|
||||
const techs = ['HTML', 'CSS', 'JavaScript']
|
||||
|
||||
return (
|
||||
<div className='app'>
|
||||
<Header data={data} />
|
||||
|
||||
<Main
|
||||
techs={techs}
|
||||
handleTime={this.handleTime}
|
||||
greetPeople={this.greetPeople}
|
||||
loggedIn={this.state.loggedIn}
|
||||
handleLogin={this.handleLogin}
|
||||
message={this.state.message}
|
||||
/>
|
||||
|
||||
<Footer date={new Date()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|