Skip to content

Commit

Permalink
day 25 has been added
Browse files Browse the repository at this point in the history
  • Loading branch information
Asabeneh committed Oct 25, 2020
1 parent 1976a2c commit 755ed69
Show file tree
Hide file tree
Showing 25 changed files with 13,434 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 30 Days of React App: Day 19
# 30 Days of React App: Day 18

In the project directory, you can run to start the project

Expand Down
2 changes: 1 addition & 1 deletion 19_projects/19_projects_boilerplate/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 30 Days of React App: Day 17
# 30 Days of React App: Day 19

In the project directory, you can run to start the project

Expand Down
2 changes: 1 addition & 1 deletion 20_projects/20_projects_boilerplate/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 30 Days of React App: Day 17
# 30 Days of React App: Day 20

In the project directory, you can run to start the project

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 30 Days of React App: Day 17
# 30 Days of React App: Day 21

In the project directory, you can run to start the project

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 30 Days of React App: Day 17
# 30 Days of React App: Day 22

In the project directory, you can run to start the project

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 30 Days of React App: Day 17
# 30 Days of React App: Day 23

In the project directory, you can run to start the project

Expand Down
4 changes: 2 additions & 2 deletions 24_projects/24_projects.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

</div>

[<< Day 23](../23_Fetching_Data_Using_Hooks/23_fetching_data_using_hooks.md) | [Day 25>>]()
[<< Day 23](../23_Fetching_Data_Using_Hooks/23_fetching_data_using_hooks.md) | [Day 25>>](../25_Custom_Hooks/25_custom_hooks.md)

![30 Days of React banner](../images/30_days_of_react_banner_day_24.jpg)

Expand All @@ -27,4 +27,4 @@

🎉 CONGRATULATIONS ! 🎉

[<< Day 23](../23_Fetching_Data_Using_Hooks/23_fetching_data_using_hooks.md) | [Day 25>>]()
[<< Day 23](../23_Fetching_Data_Using_Hooks/23_fetching_data_using_hooks.md) | [Day 25>>](../25_Custom_Hooks/25_custom_hooks.md)
2 changes: 1 addition & 1 deletion 24_projects/24_projects_boilerplate/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 30 Days of React App: Day 17
# 30 Days of React App: Day 24

In the project directory, you can run to start the project

Expand Down
224 changes: 224 additions & 0 deletions 25_Custom_Hooks/25_custom_hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
<div align="center">
<h1> 30 Days Of React: Custom Hooks</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 24](../24_projects/24_projects.md) | [Day 26>>]()

![30 Days of React banner](../images/30_days_of_react_banner_day_25.jpg)

# Custom Hooks

It is possible to make a custom hook on top of the available React hooks. For instance, when we fetch data we with use either fetch or axios to send an HTTP request and useEffect hooks to manage the React life cycle. Let's build useFetch custom hook on top of useEffect and useState.

We wrote this snippet of code in the previous section and we use useEffect hooks to fetch data from API. Now, let's convert this code to a custom hook. The naming convention for a custom hook is camelCase and it starts with the word use that is why we called our custom hook, useFetch.

```js
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import ReactDOM, { findDOMNode } from 'react-dom'

const Country = ({ country: { name, flag, population } }) => {
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>
<span>Population: </span>
{population}
</p>
</div>
</div>
)
}

const App = (props) => {
// setting initial state and method to update state
const [data, setData] = useState([])

useEffect(() => {
fetchData()
}, [])

const fetchData = async () => {
const url = 'https://restcountries.eu/rest/v2/all'
try {
const response = await fetch(url)
const data = await response.json()
setData(data)
} catch (error) {
console.log(error)
}
}

return (
<div className='App'>
<h1>Fetching Data Using Hook</h1>
<h1>Calling API</h1>
<div>
<p>There are {data.length} countries in the api</p>
<div className='countries-wrapper'>
{data.map((country) => (
<Country country={country} />
))}
</div>
</div>
</div>
)
}

const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```

Create a file name useFetch.js, and import useState and useEffect. Then transfer the state, useEffect and fetchData function part of the above code to the useFetch.js.

```js
import { useState, useEffect } from 'react'

const useFetch = () => {
const [data, setData] = useState([])

const fetchData = async () => {
const url = 'https://restcountries.eu/rest/v2/all'
try {
const response = await fetch(url)
const data = await response.json()
setData(data)
} catch (error) {
console.log(error)
}
}

useEffect(() => {
fetchData()
}, [])
}
```

Then let's make the useFetch function to take a parameter. When we fetch data the only thing which changes is the API therefore let's pass a URL parameter for the function.

```js
import { useState, useEffect } from 'react'

const useFetch = (url) => {
const [data, setData] = useState([])

const fetchData = async () => {
try {
const response = await fetch(url)
const data = await response.json()
setData(data)
} catch (error) {
console.log(error)
}
}

useEffect(() => {
fetchData()
}, [])
}

export default useFetch
```

With the above code, we should manage to fetch the data but it is advisable to put the function in the useEffect and let's move the function code the useEffect.

```js
import { useState, useEffect } from 'react'

export const useFetch = (url) => {
const [data, setData] = useState([])

useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url)
const data = await response.json()
setData(data)
} catch (error) {
console.log(error)
}
}
fetchData()
}, [url])

return data
}

export default useFetch
```

Now, let's combine everything and make it work.

```js
// index.js

import React, { useState, useEffect } from 'react'
import axios from 'axios'
import ReactDOM, { findDOMNode } from 'react-dom'
import useFetch from './useFetch'

const Country = ({ country: { name, flag, population } }) => {
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>
<span>Population: </span>
{population}
</p>
</div>
</div>
)
}

const App = (props) => {
const url = 'https://restcountries.eu/rest/v2/all'
const data = useFetch(url)

return (
<div className='App'>
<h1>Custom Hooks</h1>
<h1>Calling API</h1>
<div>
<p>There are {data.length} countries in the api</p>
<div className='countries-wrapper'>
{data.map((country) => (
<Country country={country} />
))}
</div>
</div>
</div>
)
}

const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```

# Exercises

1 Build the following application using [countries API](https://restcountries.eu/rest/v2/all).
[DEMO](https://www.30daysofreact.com/day-23/countries-data)

🎉 CONGRATULATIONS ! 🎉

[<< Day 24](../24_projects/24_projects.md) | [Day 26>>]()
23 changes: 23 additions & 0 deletions 25_Custom_Hooks/25_custom_hooks_boilerplate/.gitignore
Original file line number Diff line number Diff line change
@@ -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*
5 changes: 5 additions & 0 deletions 25_Custom_Hooks/25_custom_hooks_boilerplate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 30 Days of React App: Day 25

In the project directory, you can run to start the project

### `npm start`
34 changes: 34 additions & 0 deletions 25_Custom_Hooks/25_custom_hooks_boilerplate/package.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
}
Loading

0 comments on commit 755ed69

Please sign in to comment.