React JS
React JS
Example:
title: 'Hello',
className: 'heading'
}, 'Hello guys!')
ulDOM.id = 'ul-id'
liDOM1.innerText = 'Javascript'
liDOM1.id = 'li-1'
liDOM2.innerText = 'ReacJS'
ulDOM.appendChild(liDOM1)
ulDOM.appendChild(liDOM2)
document.body.appendChild(ulDOM)
// React
'ul',
{
id: 'ul-id',
},
React.createElement('li', {id: 'li-1'}, 'Javascript'),
)
Exercises:
divDOM.className = 'post-item'
divDOM.appendChild(h2DOM)
divDOM.appendChild(pDOM)
document.body.appendChild(divDOM)
// React
'div',
{className: 'post-item'},
ReactJS'),
cao')
)
ReactDOM.render( element, container, callback)
Example:
// React
'div',
{className: 'post-item'},
ReactJS'),
cao')
)
// React@17
// ReactDOM.render(postItem, root)
// React@18
root.render(postItem)
JSX
Example:
<script type="text/babel">
// React
const courses = [
{
},
{
},
{
name: 'ReactJS'
}
]
});
const ul = <ul>
{course}
</ul>
// React@18
root.render(ul)
</script>
React.Fragment dùng để tạo ra lớp giả để chứa 2 element cùng cấp
Example:
React.Fragment,
null,
)
const jsx = (
<React.Fragment>
<h1>Heading 1</h1>
<h2>Heading 2</h2>
</React.Fragment>
)
Example:
function Header() {
return (
)
}
render() {
return (
)
}
}
const app = (
<div className="wrapper">
<Header></Header>
<Content></Content>
<div className="footer">Footer</div>
</div>
)
root.render(app)
Exercises:
function PostItem() {
return (
<div className="post-item">
<img src="https://media-cdn.tripadvisor.com/media/photo-
s/12/45/4d/03/anhr-tren-d-i-nhin-v.jpg"/>
tính</p>
</div>
)
}
const app = (
<div className="posts-list">
<PostItem />
<PostItem />
</div>
)
root.render(app)
-----------------------------------------------------------------------------------
props
function PostItem(props) {
return (
<div className="post-item">
<img src={props.image}/>
<h2 className="post-title">{props.title}</h2>
<p className="posts-desc">{props.desciption}</p>
<p className="posts-published">{props.publishedAt}</p>
</div>
)
}
const app = (
<div className="posts-list">
<PostItem
image="https://media-cdn.tripadvisor.com/media/photo-s/12/45/4d/03/anhr-tren-
d-i-nhin-v.jpg"
/>
</div>
)
Sử dụng destructuring
function PostItem({
image,
title,
desciption,
publishedAt
}) {
return (
<div className="post-item">
<h2 className="post-title">{title}</h2>
<p className="posts-desc">{desciption}</p>
<p className="posts-published">{publishedAt}</p>
</div>
)
}
const app = (
<div className="posts-list">
<PostItem
image="https://media-cdn.tripadvisor.com/media/photo-s/12/45/4d/03/anhr-tren-
d-i-nhin-v.jpg"
/>
</div>
)
Exercise:
const courses = [
{
"id": 7,
"slug": "lessons-for-newbie",
trình web các bạn nên xem các videos tại khóa này trước nhé.",
"image": "courses/7.png",
"icon": "courses/7/6200b81f52d83.png",
"video_type": "youtube",
"video": "M62l1xA5Eu8",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 75848,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 66,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/7.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/7/6200b81f52d83.png",
"video_url": "https://www.youtube.com/watch?v=M62l1xA5Eu8",
"landing_page_url": "/courses/lessons-for-newbie",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
},
{
"id": 2,
"slug": "html-css",
"image": "courses/2.png",
"icon": "courses/2/6200aecea81de.png",
"video_type": "youtube",
"video": "R6plN3FvzFY",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 118416,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 99,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/2.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/2/6200aecea81de.png",
"video_url": "https://www.youtube.com/watch?v=R6plN3FvzFY",
"landing_page_url": "/courses/html-css",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
},
{
"id": 3,
"slug": "responsive-web-design",
dựng giao diện web responsive với Grid System, tương tự Bootstrap 4.",
"image": "courses/3.png",
"icon": "courses/3/6200afe1240bb.png",
"video_type": "youtube",
"video": "uz5LIP85J5Y",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 26794,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 91,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/3.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/3/6200afe1240bb.png",
"video_url": "https://www.youtube.com/watch?v=uz5LIP85J5Y",
"landing_page_url": "/courses/responsive-web-design",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
},
{
"id": 1,
"slug": "javascript-co-ban",
từng học lập trình. Với hơn 100 bài học và có bài tập thực hành sau mỗi bài
học.",
"image": "courses/1.png",
"icon": "courses/1/6200ad9d8a2d8.png",
"video_type": "youtube",
"video": "0SJE9dYdpps",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 75964,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 100,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/1.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/1/6200ad9d8a2d8.png",
"video_url": "https://www.youtube.com/watch?v=0SJE9dYdpps",
"landing_page_url": "/courses/javascript-co-ban",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
},
{
"id": 12,
"slug": "javascript-nang-cao",
hiểu về IIFE, closure, reference types, this keyword, bind, call, apply,
prototype, ...",
"image": "courses/12.png",
"icon": "courses/12/6200af2620118.png",
"video_type": "youtube",
"video": "MGhw6XliFgo",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 18997,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 89,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/12.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/12/6200af2620118.png",
"video_url": "https://www.youtube.com/watch?v=MGhw6XliFgo",
"landing_page_url": "/courses/javascript-nang-cao",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
},
{
"id": 14,
"slug": "windows-terminal-wsl",
tùy biến và học cách làm việc với Ubuntu là một bước quan trọng trên con đường
"image": "courses/14/624faac11d109.png",
"icon": "courses/14/624faac2ee23d.png",
"video_type": "youtube",
"video": "7ppRSaGT1uw",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 5724,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 66,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/14/624faac11d109.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/14/624faac2ee23d.png",
"video_url": "https://www.youtube.com/watch?v=7ppRSaGT1uw",
"landing_page_url": "/courses/windows-terminal-wsl",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
},
{
"id": 13,
"slug": "reactjs",
quả của khóa học này là bạn có thể làm hầu hết các dự án thường gặp với
ReactJS. Cuối khóa học này bạn sẽ sở hữu một dự án giống Tiktok.com, bạn có
thể tự tin đi xin việc khi nắm chắc các kiến thức được chia sẻ trong khóa học
này.",
"image": "courses/13/13.png",
"icon": "courses/13/6200af9262b30.png",
"video_type": "youtube",
"video": "x0fSBAgBrOQ",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 29462,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 25,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/13/13.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/13/6200af9262b30.png",
"video_url": "https://www.youtube.com/watch?v=x0fSBAgBrOQ",
"landing_page_url": "/courses/reactjs",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
},
{
"id": 6,
"slug": "nodejs",
hiểu các khái niệm khi làm Back-end và xây dựng RESTful API cho trang web.",
"image": "courses/6.png",
"icon": "courses/6/6200afb926038.png",
"video_type": "youtube",
"video": "z2f7RHgvddc",
"old_price": 0,
"price": 0,
"pre_order_price": 0,
"students_count": 21957,
"is_pro": false,
"is_selling": false,
"published_at": "2020-02-10T14:23:13.000000Z",
"is_registered": true,
"user_progress": 0,
"last_completed_at": null,
"image_url":
"https://files.fullstack.edu.vn/f8-prod/courses/6.png",
"icon_url":
"https://files.fullstack.edu.vn/f8-prod/courses/6/6200afb926038.png",
"video_url": "https://www.youtube.com/watch?v=z2f7RHgvddc",
"landing_page_url": "/courses/nodejs",
"is_coming_soon": false,
"is_pre_order": false,
"is_published": true
}
]
function CourseItem({course}) {
return (
<div className="course-item">
<h2 className="course-title">{course.title}</h2>
<p className="course-desc">{course.description}</p>
<p className="course-student">{course.students_count}</p>
</div>
)
}
function App() {
return (
<div className="wrapper">
{
<CourseItem
key={course.id}
course={course}
/>
))
}
</div>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />)
DOM events
Example:
function App() {
return (
<div className="wrapper">
<button
onClick={(e) =>
console.log(e.target)
}
>
Click me!
</button>
</div>
)
}
Exercise:
return (
<div className="course-item">
<h1 className="course-published">{course.slug}</h1>
onClick(course)} >{course.title}</h2>
<p className="course-desc">{course.description}</p>
<p className="course-student">{course.studentsCount}</p>
</div>
)
}
function App() {
alert(course.title)
}
return (
<div className="wrapper">
{
<CourseItem
key={course.id}
course={course}
onClick={handleClick}
/>
))
}
</div>
)
}
const Form = {
Input() {
return <input/>
},
Checkbox() {
}
}
function App() {
return (
<div className="wrapper">
<Form.Input />
</div>
)
}
const Form = {
Input() {
return <input/>
},
Checkbox() {
}
}
function App() {
return (
<div className="wrapper">
<Component />
</div>
)
}
const props = {}
if(href) {
Component = 'a'
props.href = href
}
if(onClick) {
props.onClick = onClick
}
return (
<Component {...props}>{title}</Component>
)
}
function App() {
return (
<div className="wrapper">
<Button
title="Click me!"
href="https://www.facebook.com/"
/>
</div>
)
}
Spread/React props
return (
<div>
<label>{label}</label>
<input {...inputProps}/>
</div>
)
}
function App() {
return (
<div className="wrapper">
<Input
label="Full name"
type="checkbox"
placeholder="Enter name...."
/>
</div>
)
}
Children props
function Button({children}) {
return (
<button>{children}</button>
)
}
function App() {
return (
<div className="wrapper">
<Button>Click me!</Button>
</div>
)
}
Render props
function List({data}) {
return (
<ul>
{data.map(item =>
<li key={item}>{item}</li>
)}
</ul>
)
}
function App() {
return (
<div className="wrapper">
<List data={cars}/>
</div>
)
}
return (
<ul>
</ul>
)
}
function App() {
return (
<div className="wrapper">
<List data={cars}>
</List>
</div>
)
}
useState()
function App() {
setCounter(counter+1)
}
return (
<h1>{counter}</h1>
<button onClick={handleIncrease}>Increase</button>
</div>
);
function App() {
return total
})
const handleIncrease = () => {
setCounter(counter + 1)
}
return (
<h1>{counter}</h1>
<button onClick={handleIncrease}>Increase</button>
</div>
);
function App() {
age: 20,
})
setInfo({
...info,
})
}
return (
<h1>{JSON.stringify(info)}</h1>
<button onClick={handleUpdate}>Update</button>
</div>
);
}
Example:
Random gifts
const gifts = [
'CPU i9',
'RGB Keyboard',
function App() {
setGift(gifts[index])
}
return (
</div>
);
Two-way building
function App() {
console.log(name)
return (
</div>
);
function App() {
console.log({
name,
})
}
return (
<button onClick={handleSubmit}>Register</button>
</div>
);
const courses = [
{
id: 1,
},
{
id: 2,
name: 'Javascript'
},
{
id: 3,
name: 'ReactJS'
},
function App() {
console.log(checked)
setChecked(prev => {
if(isChecked) {
} else {
}
})
}
console.log({ids: checked})
}
return (
<div key={course.id}>
checked={checked.includes(course.id)}/>
<label>{course.name}</label>
</div>
))}
<button onClick={handleSubmit}>Register</button>
</div>
);
function App() {
return storageJobs
});
setJobs((prev) => {
localStorage.setItem('jobs', jsonJobs)
return newJobs
});
setJob('');
};
return (
<button onClick={handleSubmit}>Add</button>
<ul>
<li key={index}>{job}</li>
))}
</ul>
</div>
);
Mounted / Unmounted
function App() {
return (
</div>
);
}
useEffect
// 1. useEffect(callback)
// 2. useEffect(callback, [])
// 3. useEffect(callback, [deps])
// -----------------------------
// 3. Cleanup function luôn được gọi trước khi callback được gọi (trừ lần
mounted)
function Content() {
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(posts => {
setPosts(posts)
})
}, [])
return (
<div>
<input value={title} onChange={e =>
setTitle(e.target.value)}></input>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
)
}
Call API
function Content() {
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/${type}`)
.then(posts => {
setPosts(posts)
})
}, [type])
return (
<div>
{tabs.map(tab => (
</button>
))}
setTitle(e.target.value)}></input>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
)
}
Button go to top
function Content() {
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/${type}`)
}, [type])
useEffect(() => {
setShowGoToTop(true)
} else {
setShowGoToTop(false)
}
}
window.addEventListener('scroll', handleScroll)
// Cleanup function
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
return (
<div>
{tabs.map(tab => (
<button key={tab}
'#333' } : {}}
>{tab}</button>
))}
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
{showGoToTop && (
</button>
)}
</div>
)
}
Resize
function Content() {
useEffect(() => {
setWidth(window.innerWidth)
}
window.addEventListener('resize', handleResize)
// Cleanup function
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
return (
<div>
<h1>{width}</h1>
</div>
)
}
Countdown
function Content() {
useEffect(() => {
}, 1000)
}, [])
return (
<div>
<h1>{countdown}</h1>
</div>
)
}
Preview avatar
function Content() {
useEffect(() => {
return () => {
}
}, [avatar])
setAvatar(file)
}
return (
<div>
{avatar && (
)}
</div>
)
}
Fake app chat
// Fake comments
function emitComment(id) {
setInterval(() => {
window.dispatchEvent(
new CustomEvent(`lesson-${id}`, {
})
)
}, 2000)
emitComment(1)
emitComment(2)
emitComment(3)
const lessons = [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
}
function Content() {
useEffect(() => {
console.log(detail)
}
window.addEventListener(`lesson-${lessonId}`, handleComment)
return () => {
window.removeEventListener(`lesson-${lessonId}`, handleComment)
}
}, [lessonId])
return (
<div>
<ul>
{lessons.map(lesson => (
<li key={lesson.id}
style={{color: lessonId === lesson.id ? 'red' :
'#333'}}
>
{lesson.name}
</li>
))}
</ul>
</div>
)
useLayoutEffect
// useeffect
// 3. Render lại UI
// useLayoutEffect
// 5. Render lại UI
function Content() {
useLayoutEffect(() => {
if(count > 3)
setCount(0)
}, [count])
setCount(count + 1)
}
return (
<div>
<h1>{count}</h1>
<button onClick={handleRun}>Run</button>
</div>
)
useRef: Lưu giá trị qua một tham chiếu bên ngoài function component
function Content() {
}, 1000)
console.log('start ->',timerId.current)
}
clearInterval(timerId.current)
console.log('stop ->',timerId.current)
}
return (
<h1>{count}</h1>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)
function Content() {
useEffect(() => {
prevCount.current = count
}, [count])
useEffect(() => {
console.log(h1Ref)
})
}, 1000)
console.log('start ->',timerId.current)
}
clearInterval(timerId.current)
console.log('stop ->',timerId.current)
}
console.log(count, prevCount.current)
return (
<h1 ref={h1Ref}>{count}</h1>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)
useCallback: Giúp tránh tạo ra những hàm mới một cách không cần thiết trong function component
function App() {
}, [])
return (
<Content onIncrease={increase}/>
<h1 >{count}</h1>
</div>
)
useMemo: Giúp tránh thực hiện lại một logic nào đó không cần thiết
function App() {
setProducts([...products, {
name,
price: +price
}])
setName('')
setPrice('')
nameRef.current.focus()
}
return result
}, [products])
return (
<input
ref={nameRef}
value={name}
placeholder="Enter name..."
></input>
<br></br>
<input
value={price}
placeholder="Enter price..."
></input>
<br></br>
<button onClick={handleSubmit}>Add</button>
<br></br>
Total: {total}
<ul>
))}
</ul>
</div>
)
}
useReducer: Cùng cấp cho người dùng có thêm sự lựa chọn để sử dụng state cho function
conponent
// Init State
const initState = 0
// Actions
// Reducer
console.log('reducer running...')
switch(action) {
case UP_ACTION:
return state + 1
case DOWN_ACTION:
return state - 1
default:
}
function App() {
return (
<h1>{count}</h1>
<button
>Down</button>
<button
>Up</button>
</div>
)
const intitState = {
job: '',
jobs: []
return {
type: SET_JOB,
payLoad
}
return {
type: ADD_JOB,
payLoad
}
}
const deleteJob = payLoad => {
return {
type: DELETE_JOB,
payLoad
}
switch (action.type) {
case SET_JOB:
return {
...state,
job: action.payLoad
}
case ADD_JOB:
return {
...state,
}
case DELETE_JOB:
newJobs.splice(action.payLoad, 1)
return {
...state,
jobs: newJobs
}
default:
}
return state
}
function App() {
dispatch(addJob(job))
dispatch(setJob(''))
inputRef.current.focus()
}
return (
<h3>Todo</h3>
<input
ref={inputRef}
value={job}
placeholder="Enter todo..."
onChange={e => {
dispatch(setJob(e.target.value))
}}
></input>
<button onClick={handleSubmit}>Add</button>
<ul>
<li key={index}>
{job}
</li>
))}
</ul>
</div>
)