Day_10 has been published

pull/52/head
Asabeneh 4 years ago
parent 69f965097b
commit ba2da20c2d

4
.gitignore vendored

@ -1,6 +1,6 @@
draft.md
react-for-everyone.md
component.md
10_Day_Events
11_Day_Forms
11_Day_Events
12_Day_Forms

@ -0,0 +1,488 @@
<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 9](../09_Day_Conditional_Rendering/09_conditional_rendering.md) | [Day 11 >>](../11_Day_Events/10_events.md)
![30 Days of React banner](../images/30_days_of_react_banner_day_10.jpg)
# React Project Folder Structure and File Naming
There is no strictly to use a single folder structure or file naming in React project. Most of the time, these kind of choice can be made by a team or a company may have a guideline. There is no right or wrong way of structuring a React project but some structures are better than the others for scalability, ease of working on files and easy to understand structure. If you like to learn further about folder structure you may check the following articles.
- [React Folder Structure by https://www.devaradise.com ](https://www.devaradise.com/react-project-folder-structure)
- [React Folder Structure by www.robinwieruch.de ](https://www.robinwieruch.de/react-folder-structure)
- [React Folder Structure by Faraz Ahmad](https://dev.to/farazamiruddin/an-opinionated-guide-to-react-folder-structure-file-naming-1l7i)
- [React Folder Structure by https://maxrozen.com/](https://maxrozen.com/guidelines-improve-react-app-folder-structure/)
I use a mix of different conventions. If you like you can follow it but please stick in a structure which you think makes sense for you.
## File Naming
In all my React project, I will use CamelCase file name for all components. I prefer to use descriptive long name.
## Folder
I found it easy to put all images, icons and fonts in an asset and all CSS style sheets in styles folder. All components will be in a component folder.
So far, we have been working on index.js file. We have lots of component on index.js. Today we will move every component to a single file. We import all the file to App.js. In the process, you will see my folder structure. We are in src directory. All the folder structure will be inside the src directory. Let's start from the index.js file. In addition to index.js file, let's create an App.js file and move most of the components we had to App.js for the time being.
The index.js is your getaway to connect the component with index.html.
```js
// src/index.js
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
const App = () => <h1>Welcome to 30 Days Of React</h1>
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
In the above snippet of code, we have the App component. Let's create the App component to its own file, App.js
```js
//src/App.js
import React from 'react
const App = () => <h1>Welcome to 30 Days Of React</h1>
```
We have to export the component to import it in another file. We can export it as a default or named export. In one file, we can make one default export and many named exports. First, let's implement it using name export and later in default export.
We just add the keyword export before _let_ or _const_ to make a named export.
```js
//src/App.js
import React from 'react
export const App = () => <h1>Welcome to 30 Days Of React</h1>
```
Now, let's import the App component from the App.js file to index.js.
```js
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { App } from './App'
// class based component
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
We saw a named export and now let's implement it with default export. We can do it in two ways but it is recommended to use the second way if we are exporting components because sometimes we may bind a component with another higher order component.
```js
//src/App.js
import React from 'react
export default const App = () => <h1>Welcome to 30 Days Of React</h1>
```
```js
//src/App.js
import React from 'react
const App = () => <h1>Welcome to 30 Days Of React</h1>
export default App
```
If a component is exported as default we do not need curly bracket during import.
```js
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
// class based component
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
If you remember, we created the following components so far and we have been putting them together. It is not easy to work like this. Now we will move them all components to a separate file.
```js
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import asabenehImage from './images'
import { countriesData } from './data/countries'
// 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>
)
}
}
const Country = ({
country: { name, capital, flag, languages, population, currency },
}) => {
const formatedCapital =
capital.length > 0 ? (
<>
<span>Capital: </span>
{capital}
</>
) : (
''
)
const formatLanguage = languages.length > 1 ? `Languages` : `Language`
return (
<div className='country'>
<div className='country_flag'>
<img src={flag} alt={name} />
</div>
<h3 className='country_name'>{name.toUpperCase()}</h3>
<div class='country_text'>
<p>{formatedCapital}</p>
<p>
<span>{formatLanguage}: </span>
{languages.join(', ')}
</p>
<p>
<span>Population: </span>
{population.toLocaleString()}
</p>
<p>
<span>Currency: </span>
{currency}
</p>
</div>
</div>
)
}
// User Card Component
const UserCard = () => (
<div className='user-card'>
<img src={asabenehImage} alt='asabeneh image' />
<h2>Asabeneh Yetayeh</h2>
</div>
)
// Hexadecimal color generator
const hexaColor = () => {
let str = '0123456789abcdef'
let color = ''
for (let i = 0; i < 6; i++) {
let index = Math.floor(Math.random() * str.length)
color += str[index]
}
return '#' + color
}
const HexaColor = () => <div>{hexaColor()}</div>
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'>
{this.state.backgroundColor}
<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)
```
## Components Folder
Inside the src directory will pull all the components
```sh
src
App.js
index.js
components
-auth
-Signup.js
-Signin.js
-Forgotpassword.js
-Resetpassord.js
header
-Header.js
footer
-Footer.js
assets
-images
-icnons
- fonts
styles
-button.js
-button.scss
utils
-random-id.js
-display-time.js
-generate-color.js
shared
-Button.js
-InputField.js
-TextAreaField.js
```
Let's create components directory inside src and inside components let's create header director. Create Header.js inside the header directory.
```js
// src/components/header/Header.js
import React from 'react'
const Header = (props) => {
return (
<header>
<div className='header-wrapper'>
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
)
}
export default Header
```
Similar to the Header let's move all the components to their respective files.
All the CSS files on index.html will moved into styles folder and after that each part has been split its respective file, try to check the styles folder.
# Exercises
## Exercises
1. What is the importance of React Folder Structure and File Naming
2. How do we export file
3. How do we import file
4. Make a component of module and export it as named or default export
5. Make a component or module and import it
6. Change all the components you have to different folder structure
🎉 CONGRATULATIONS ! 🎉
[<< Day 9](../09_Day_Conditional_Rendering/09_conditional_rendering.md) | [Day 11 >>](../11_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,20 @@
<!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|Aldrich:300,400, 500|Oswald:300,400, 500|Raleway: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>
</head>
<body>
<div id="root"></div>
</body>
</html>

@ -0,0 +1,65 @@
import React from 'react'
import Header from './components/header/Header'
import Main from './components/main/Main'
import Footer from './components/footer/Footer'
import { countriesData } from './data/countries'
import asabenehImage from './assets/images/asabeneh.jpg'
import { showDate } from './utils/display-date-and-time'
class App extends React.Component {
state = {
loggedIn: false,
techs: ['HTML', 'CSS', 'JS'],
message: 'Click show time or Greet people to change me',
country: countriesData[1],
}
handleLogin = () => {
this.setState({
loggedIn: !this.state.loggedIn,
})
}
handleTime = () => {
let message = 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: new Date(),
}
const techs = ['HTML', 'CSS', 'JavaScript']
const user = { ...data.author, image: asabenehImage }
return (
<div className='app'>
{this.state.backgroundColor}
<Header data={data} />
<Main
techs={techs}
handleTime={this.handleTime}
greetPeople={this.greetPeople}
loggedIn={this.state.loggedIn}
handleLogin={this.handleLogin}
message={this.state.message}
country={this.state.country}
user={user}
/>
<Footer date={new Date()} />
</div>
)
}
}
export default App

@ -0,0 +1,13 @@
import React from 'react'
import { hexaColor } from '../../utils/hexadecimal-color-generator'
const HexaColor = (props) => {
return (
<div style={{ textAlign: 'center', border: '2px solid', height: 50 }}>
{hexaColor()}
</div>
)
}
HexaColor.propTypes = {}
export default HexaColor

@ -0,0 +1,40 @@
import React from 'react'
const Country = ({
country: { name, capital, flag, languages, population, currency },
}) => {
const formatedCapital =
capital.length > 0 ? (
<>
<span>Capital: </span>
{capital}
</>
) : (
''
)
const formatLanguage = languages.length > 1 ? `Languages` : `Language`
return (
<div className='country'>
<div className='country_flag'>
<img src={flag} alt={name} />
</div>
<h3 className='country_name'>{name.toUpperCase()}</h3>
<div class='country_text'>
<p>{formatedCapital}</p>
<p>
<span>{formatLanguage}: </span>
{languages.join(', ')}
</p>
<p>
<span>Population: </span>
{population.toLocaleString()}
</p>
<p>
<span>Currency: </span>
{currency}
</p>
</div>
</div>
)
}
export default Country

@ -0,0 +1,11 @@
import React from 'react'
const Footer = ({ date }) => {
return (
<footer>
<div className='footer-wrapper'>
<p>Copyright {date.getFullYear()}</p>
</div>
</footer>
)
}
export default Footer

@ -0,0 +1,29 @@
import React from 'react'
import PropTypes from 'prop-types'
import { showDate } from '../../utils/display-date-and-time'
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>
)
}
export default Header

@ -0,0 +1,118 @@
import React from 'react'
import Button from '../shared/Button'
import HexaColr from '../color/HexaColor'
import Country from '../country/Country'
import UserCard from '../user/UserCard'
// 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',
}
// 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
}
}
const Message = ({ message }) => (
<div
style={{
border: '2px solid #61dbfb',
margin: 25,
padding: 10,
}}
>
<h3>{message}</h3>
</div>
)
const Login = () => (
<div>
<h3>Please Login</h3>
</div>
)
const Welcome = (props) => (
<div style={{ border: '2px solid rgb(0,255,0', margin: 10, padding: 10 }}>
<h2>Welcome to 30 Days Of React</h2>
</div>
)
// Main Component
// Class Component
class Main extends React.Component {
render() {
const {
techs,
greetPeople,
handleTime,
loggedIn,
handleLogin,
message,
country,
user,
} = 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>
<UserCard user={user} />
{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} />
<HexaColr />
<HexaColr />
<Country country={country} />
</div>
</main>
)
}
}
export default Main

@ -0,0 +1,11 @@
import React from 'react'
// A button component
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
)
export default Button

@ -0,0 +1,15 @@
import React from 'react'
// User Card Component
const UserCard = ({ user: { firstName, lastName, image } }) => (
<div className='user-card'>
<img src={image} alt='asabeneh image' />
<h2>
{firstName}
{lastName}
</h2>
</div>
)
export default UserCard

@ -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 },
]

@ -0,0 +1,10 @@
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './styles/index.css'
// class based component
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

@ -0,0 +1,57 @@
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
line-height: 1.5;
font-family: 'Roboto';
font-weight: 300;
color: black;
overflow-x: hidden;
font-size: 110%;
}
#root {
min-height: 100%;
position: relative;
letter-spacing: 1.25px;
}
.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;
}
main {
padding: 10px;
padding-bottom: 60px;
}
ul {
margin-left: 15px;
}
ul li {
list-style: none;
}

@ -0,0 +1,60 @@
/* Countries*/
.country {
max-width: 50rem;
min-width: 50rem;
height: 35rem;
text-align: center;
margin: 0.75rem auto;
padding: 2rem;
border-radius: 0.2rem;
background: white;
box-shadow: 0 0.1rem 1rem #cfc9c7;
}
.country:hover {
box-shadow: 0 0.1rem 1rem #cfc9c7;
-webkit-transition: all 0.2s ease-in;
transform: scale(1.015);
}
.country_flag {
height: 12rem;
width: 20rem;
text-align: center;
margin: auto;
}
.country img {
display: block;
margin: auto;
max-width: 100%;
max-height: 100%;
min-width: 100%;
min-height: 100%;
border-radius: 0.3rem;
box-shadow: 0 0 0.6rem 0.2rem rgb(241, 225, 225);
}
.country_name {
font-size: 1.6rem;
color: #ffa500;
letter-spacing: 0.075rem;
font-weight: bolder;
margin: 1rem;
color: #414141;
font-weight: 900;
}
.country p {
font-size: 1.6rem;
font-weight: 500;
padding: 0.2rem;
color: #747474;
text-align: left;
letter-spacing: 0.05rem;
}
.country span {
font-weight: 600;
}

@ -0,0 +1,14 @@
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;
}

@ -0,0 +1,5 @@
header {
background-color: #61dbfb;
padding: 25;
padding: 10px;
}

@ -0,0 +1,8 @@
/* == General style === */
/* This CSS has to be broken into small files */
@import './common.css';
@import './header.css';
@import './footer.css';
@import './user-card.css';
@import './country.css';

@ -0,0 +1,7 @@
.user-card {
margin-top: 10px;
}
.user-card > img {
border-radius: 50%;
width: 14%;
}

@ -0,0 +1,21 @@
export 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}`
}

@ -0,0 +1,10 @@
// Hexadecimal color generator
export const hexaColor = () => {
let str = '0123456789abcdef'
let color = ''
for (let i = 0; i < 6; i++) {
let index = Math.floor(Math.random() * str.length)
color += str[index]
}
return '#' + color
}

@ -32,9 +32,11 @@
|07|[Class Components](./07_Day_Class_Components/07_class_components.md)|
|08|[States](./08_Day_States/08_states.md)|
|09|[Conditional Rendering](./09_Day_Conditional_Rendering/09_conditional_rendering.md)|
|10|[Events 😞]()|
|11|[Forms 😞]()|
|10|[React Project Folder Structure](./10_React_Project_Folder_Structure/10_react_project_folder_structure.md)|
|11|[Events 😞]()|
|12|[Forms 😞]()|
|13|[Controlled and Uncondrolled Component 😞]()|
|13|[Component Life Cycles😞]()|
🧡🧡🧡 HAPPY CODING 🧡🧡🧡<div>

Loading…
Cancel
Save