forked from Asabeneh/30-Days-Of-React
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
13,434 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
21_Introducing_Hooks/21_introducing_hooks_boilerplate/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
23_Fetching_Data_Using_Hooks/23_fetching_data_using_hooks_boilerplate/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>>]() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
] | ||
} | ||
} |
Oops, something went wrong.