@ -0,0 +1,144 @@
|
||||
<div align="center">
|
||||
<h1> 30 Days Of React: useRef</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 25](../25_Custom_Hooks/25_custom_hooks.md) | [Day 27>>]()
|
||||
|
||||
![30 Days of React banner](../images/30_days_of_react_banner_day_27.jpg)
|
||||
|
||||
# useRef
|
||||
|
||||
In this challenge we have covered, how to handle uncontrolled input data. In this section, we will use the useRef hooks to get input data or to access any DOM element in your React application.
|
||||
|
||||
The useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
|
||||
|
||||
In the following example, we see how to get data from input and access elements from the DOM tree using useRef hook.
|
||||
|
||||
## Getting Data from input
|
||||
|
||||
Let's get data from uncontrolled input element.
|
||||
|
||||
```js
|
||||
import React, { useRef } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const App = (props) => {
|
||||
const ref = useRef(null)
|
||||
const onClick = () => {
|
||||
let value = ref.current.value
|
||||
alert(value)
|
||||
}
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1>How to use data from uncontrolled input using useRef</h1>
|
||||
<input type='text' ref={ref} />
|
||||
<br />
|
||||
<button onClick={onClick}>Get Input Data</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
## Focus
|
||||
|
||||
Using the useRef we can trigger the focus event on input.
|
||||
|
||||
```js
|
||||
import React, { useRef } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const App = (props) => {
|
||||
const ref = useRef(null)
|
||||
const onClick = () => {
|
||||
ref.current.focus()
|
||||
}
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1>How to focus on input element useRef</h1>
|
||||
<input type='text' ref={ref} />
|
||||
<br />
|
||||
<button onClick={onClick}>Click to Focus on input</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
## Getting Content from DOM tree
|
||||
|
||||
Don't touch the DOM when you develop a React application because React has its own way to manipulate the DOM using the virtual DOM. In case, we get interested to get some content from the DOM tree we can use the useRef hook. See the example:
|
||||
|
||||
```js
|
||||
import React, { useRef } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const App = (props) => {
|
||||
const ref = useRef(null)
|
||||
const onClick = () => {
|
||||
let content = ref.current.textContent
|
||||
alert(content)
|
||||
console.log(content)
|
||||
}
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1 ref={ref}>How to getting content from the DOM tree</h1>
|
||||
<button onClick={onClick}>Getting Content</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
||||
```
|
||||
|
||||
## Accessing and Styling a DOM element
|
||||
|
||||
We can access and style an element from the DOM tree. See the example below:
|
||||
|
||||
```js
|
||||
import React, { useRef } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const App = (props) => {
|
||||
const ref = useRef(null)
|
||||
const onClick = () => {
|
||||
ref.current.style.backgroundColor = '#61dbfb'
|
||||
ref.current.style.padding = '50px'
|
||||
ref.current.style.textAlign = 'center'
|
||||
}
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1 ref={ref}>How to style HTML from the DOM tree using useRef</h1>
|
||||
<button onClick={onClick}>Style it</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement
|
||||
```
|
||||
|
||||
# Exercises
|
||||
|
||||
1. Coming...
|
||||
|
||||
🎉 CONGRATULATIONS ! 🎉
|
||||
|
||||
[<< Day 25](../25_Custom_Hooks/25_custom_hooks.md) | [Day 27>>]()
|
@ -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 25
|
||||
|
||||
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,20 @@
|
||||
import React, { useRef } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
const App = (props) => {
|
||||
const ref = useRef(null)
|
||||
const onClick = () => {
|
||||
ref.current.style.backgroundColor = '#61dbfb'
|
||||
ref.current.style.padding = '50px'
|
||||
ref.current.style.textAlign = 'center'
|
||||
}
|
||||
return (
|
||||
<div className='App'>
|
||||
<h1 ref={ref}>How to style HTML from the DOM tree using useRef</h1>
|
||||
<button onClick={onClick}>Style it</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
@ -0,0 +1,86 @@
|
||||
/* == 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%;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
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
|
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 113 KiB |