ReactJS - Cheatsheet
Tổng hợp Cheatsheet ReactJS - Hướng dẫn cơ bản.
🔖 Gợi ý từ Admin
📝 Tài liệu phỏng vấn kiến thức lập trình: Xem tại đây!!!
📌 Tìm hiểu về thuật toán: Xem tại đây!!!
📌 Roadmaps - Lộ trình trở thành một lập trình viên: Xem tại đây!!!
⚡️ Cheatsheet các ngôn ngữ lập trình: Xem tại đây!!!
⚡️ Handbook lập trình: Xem tại đây!!!
ReactJS là lựa chọn phù hợp để bạn thiết kế giao diện người dùng. Cho dù bạn là nhà phát triển dày dặn kinh nghiệm hay mới bắt đầu phát triển web, bài viết này sẽ giải thích các components, element và ý tưởng chính của React. Hy vọng sẽ giúp bạn nắm vững cú pháp JSX, thuộc tính React và các điều kiện.
1. Tổng hợp Cheatsheet ReactJS
Bảng Cheat Sheet React là một tài liệu tham khảo ngắn gọn và nhanh chóng về các phương thức React thường được sử dụng.
1. React Element
Các phần tử React phản ánh cú pháp của các phần tử HTML thông thường. Bất kỳ phần tử HTML hợp lệ nào cũng có thể được biểu diễn trong React.
<h1>My Header</h1>
<p>My paragraph</p>
<button>My button</button>
Các phần tử React này được xây dựng bằng JSX, một đặc trưng độc đáo của React kết hợp cú pháp HTML với các hàm JavaScript.
Tuy nhiên, do bản chất của JSX là các hàm JavaScript (không phải HTML), có một số khác biệt về cú pháp. Đáng chú ý, các phần tử đơn tag, như phần tử img, phải tự đóng và kết thúc bằng dấu gạch chéo phía trước /.
<img src="my-image.png" />
<br />
<hr />
2. React Element Attributes
JSX giới thiệu cú pháp cho các thuộc tính, tuân theo quy ước camelCase của JavaScript. Ví dụ, thuộc tính class trong HTML trở thành className trong JSX.
<div className='container'></div>
3. React Element Styles
Áp dụng style inline trong JSX đòi hỏi sử dụng dấu ngoặc nhọn kép thay vì dấu ngoặc kép. Style không được biểu diễn dưới dạng chuỗi đơn giản, mà là các thuộc tính trong đối tượng (object).
<h1 style={{ fontSize: 24, margin: '0 auto', textAlign: 'center' }}>My header</h1>
4. React Fragments
React cung cấp một phần tử đặc biệt được gọi là fragment
để đáp ứng yêu cầu trả về tất cả các phần tử trong một component cha duy nhất. Điều này rất quan trọng vì React yêu cầu một "cha" duy nhất cho các phần tử được trả về. Nếu bạn không muốn sử dụng một phần tử chứa như div, bạn có thể sử dụng fragment:
// Valid syntax
function MyComponent() {
return (
<>
<h1>My header</h1>
<p>My paragraph</p>
</>
);
}
Fragment có thể được viết theo cú pháp thông thường hoặc cú pháp tắt: <React.Fragment></React.Fragment>
hoặc <></>
.
5. React Components
Trong Hook useState của React, chúng ta có khả năng tổ chức các nhóm phần tử thành những gì chúng ta gọi là các thành phần (components) React.
Một component hàm cơ bản được tạo ra theo cách rất giống với một hàm JavaScript tiêu chuẩn, với một vài điểm cần lưu ý.
Đầu tiên, tên của component phải bắt đầu bằng một chữ cái in hoa. Tức là, chúng ta sẽ chọn cái gì đó như MyComponent thay vì myComponent. Hơn nữa, không giống như các hàm JavaScript thông thường, các components phải trả về JSX một cách khéo léo, hợp lệ.
Cú pháp cơ bản của một component hàm React như sau:
function App() {
return <div>Hello world!</div>;
}
6. React Props
Trong thế giới của React, các component có khả năng nhận dữ liệu được truyền xuống cho chúng, mà chúng ta gọi là props.
Những props này được gửi từ component cha đến component con. Một ví dụ minh họa, xem xét việc truyền một prop có tên "name" từ component App đến component User:
function App() {
return <User name='John Doe' />;
}
function User(props) {
return <h1>Hello, {props.name}</h1>; // Hello, John Doe!
}
Vì props về cơ bản là một đối tượng, chúng ta có thể trích xuất giá trị của prop "name" trong component User thông qua react hooks.
Để tiếp cận mã nguồn dễ hơn, đặc biệt khi xử lý một prop đơn như "name", ta có thể sử dụng cấu trúc hủy đối tượng (object destructuring):
function App() {
return <User name='John Doe' />;
}
function User({ name }) {
return <h1>Hello, {name}!</h1>; // Hello, John Doe!
}
Đáng chú ý là bất kỳ giá trị JavaScript nào, bao gồm cả các phần tử và component khác, đều có thể được truyền dưới dạng prop.
7. React Children Props
Props cũng có thể được truyền bằng cách đặt dữ liệu giữa thẻ mở và thẻ đóng của một component. Những props được truyền theo cách này nằm trong thuộc tính children.
Ví dụ, xem xét việc truyền nội dung giữa các thẻ của component User:
function App() {
return (
<User>
<h1>Hello, John Doe!</h1>
</User>
);
}
function User({ children }) {
return children; // Hello, John Doe!
}
8. React Conditionals
Các component và phần tử React có thể được hiển thị theo điều kiện. Một cách tiếp cận là sử dụng một câu lệnh return riêng biệt với một câu lệnh if.
function App() {
const isAuthUser = useAuth();
if (isAuthUser) {
// if our user is authenticated, let them use the app
return <AuthApp />;
}
// if user is not authenticated, show a different screen
return <UnAuthApp />;
}
Để sử dụng toán tử ba ngôi, hãy đặt toàn bộ điều kiện trong dấu ngoặc nhọn.
function App() {
const isAuthUser = useAuth();
return (
<>
<h1>My App</h1>
{isAuthUser ? <AuthApp /> : <UnAuthApp />}
</>
);
}
9. React Lists
Danh sách các component React có thể được tạo ra bằng cách sử dụng hàm .map()
, cho phép chúng ta lặp qua các mảng dữ liệu và tạo ra JSX.
Xem xét ví dụ về việc xuất ra danh sách các cầu thủ bóng đá bằng cách sử dụng component SoccerPlayer:
function SoccerPlayers() {
const players = ['Messi', 'Ronaldo', 'Laspada'];
return (
<div>
{players.map((playerName) => (
<SoccerPlayer key={playerName} name={playerName} />
))}
</div>
);
}
Việc bao gồm prop key khi lặp qua một mảng dữ liệu là rất cần thiết, và key này phải được gán một giá trị duy nhất, không chỉ là chỉ số phần tử. Trong ví dụ trên, một giá trị duy nhất, playerName, đóng vai trò là key.
10. React Context
React Context hoạt động như một cơ chế để truyền dữ liệu một cách liền mạch trong cây component, loại bỏ nhu cầu phải dựa hoàn toàn vào props.
Thách thức với props nằm ở việc đôi khi cần phải truyền chúng qua các component trung gian không nhất thiết cần dữ liệu - một vấn đề thường được gọi là props drilling.
Xem xét tình huống đơn giản này nơi props được truyền không cần thiết qua một component 'Body':
function App() {
return <Body name='John Doe' />;
}
function Body({ name }) {
return <Greeting name={name} />;
}
function Greeting({ name }) {
return <h1>Welcome, {name}</h1>;
}
Trước khi sử dụng Context, nên xem xét liệu các components có thể được cấu trúc tốt hơn để tránh việc truyền props qua các phần không cần thiết.
Khi triển khai Context, chúng ta sử dụng hàm createContext được cung cấp bởi React. Hàm này có thể được gọi với một giá trị ban đầu trở thành điểm khởi đầu cho context.
Context kết quả bao gồm một Provider và một thuộc tính Consumer, cả hai đều hoạt động như các component. Provider được bao quanh cây component nơi cần phải truyền dữ liệu, trong khi Consumer được đặt trong thành phần được thiết lập để sử dụng giá trị này.
import { createContext } from 'react';
const NameContext = createContext('');
function App() {
return (
<NameContext.Provider value='John Doe'>
<Body />
</NameContext.Provider>
);
}
function Body() {
return <Greeting />;
}
function Greeting() {
return <NameContext.Consumer>{(name) => <h1>Welcome, {name}</h1>}</NameContext.Consumer>;
}
Bằng cách áp dụng cách tiếp cận này, chúng ta cải thiện việc tổ chức các component của mình và tránh cần phải truyền props qua các phần tử thừa trong cây component.
11. React Hooks
React Hooks đã xuất hiện cùng với phiên bản React 16.8, cung cấp một cách tiện lợi để tích hợp logic tái sử dụng và có trạng thái vào các thành phần hàm của React, từ đó mở rộng khả năng của chúng ngoài những gì truyền thống chỉ thuộc về các class components.
Những hooks này giúp chúng ta tận dụng những tính năng trước đây chỉ dành cho các class components, và chúng ta thậm chí có thể tạo ra những custom hooks riêng để trang bị cho ứng dụng của mình các tính năng cụ thể. Thư viện React đã tích hợp nhiều hooks cần thiết, và chúng ta sẽ đi sâu vào sáu trong số đó mà quan trọng cho việc hiểu của bạn:
- useState
- useEffect
- useRef
- useContext
- useCallback
- useMemo
12. React useState Hook
Hook useState của React phục vụ một mục đích đơn giản - nó cho phép sử dụng các giá trị có trạng thái trong các function component.
Thay vì dựa vào một biến cơ bản, useState được sử dụng vì khi trạng thái được thay đổi, component sẽ được render lại, thường là để hiển thị giá trị đã được cập nhật.
Chúng ta gọi useState ở đầu của component, cho phép chúng ta cung cấp một giá trị ban đầu để điền vào biến trạng thái của nó.
import { useState } from 'react';
function MyComponent() {
const [stateValue, setStateValue] = useState(initialValue);
}
// For a practical demonstration, let’s consider a basic example involving the incrementation of a counter.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function updateCount() {
setCount(count + 1);
}
return <button onClick={updateCount}>Count is: {count}</button>;
}
Điều này cho thấy cách hook useState đơn giản hóa việc quản lý trạng thái trong các function component.
13. React useEffect Hook
Hook useEffect của React được sử dụng khi chúng ta cần tương tác với môi trường bên ngoài, chẳng hạn như thực hiện các lời gọi API. Mục đích chính của nó là xử lý các hiệu ứng phụ (side effect), bao gồm các hoạt động ngoài ứng dụng của chúng ta với các kết quả không thể đoán trước.
Cú pháp cơ bản của useEffect bao gồm cung cấp một hàm làm đối số đầu tiên và một mảng làm đối số thứ hai.
import { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// Perform side effect here
}, []);
}
Để minh họa cách sử dụng nó trong việc tìm nạp và hiển thị danh sách các bài đăng, hãy xem xét ví dụ sau:
import React, { useState, useEffect } from 'react';
function PostList() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((data) => setPosts(data));
}, []);
return (
<div>
{posts.map((post) => (
<div key={post.id}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</div>
))}
</div>
);
}
export default PostList;
Trong ví dụ này, chúng ta sử dụng hook useState
để quản lý trạng thái của posts
, và hook useEffect
để tìm nạp dữ liệu từ API. Khi dữ liệu được tìm nạp thành công, chúng ta cập nhật trạng thái posts
bằng cách sử dụng hàm setPosts
.
Nếu chúng ta cần một giá trị từ bên ngoài effect function, nó phải được bao gồm trong mảng phụ thuộc (dependencies array). Nếu giá trị đó thay đổi, effect function sẽ được thực thi lại.
Để minh họa, hãy xem xét đoạn mã này, nó chuyển đổi lớp "overflow-hidden" trên phần tử body dựa trên việc menu di động đang mở hay đóng:
function Mobile({ open }) {
useEffect(() => {
const body = document.querySelector('#__next');
if (open) {
body.classList.add('overflow-hidden');
} else {
body.classList.remove('overflow-hidden');
}
}, [open]);
// ...
}
14. React useRef Hook
Hook useRef của React cung cấp một cổng trực tiếp đến một phần tử JSX, cung cấp một cơ chế để truy cập nó mà không cần đến prop drilling.
Để sử dụng useRef, chỉ cần gọi hook, lấy giá trị trả về và gán nó cho prop ref của phần tử React mong muốn. Điều quan trọng cần lưu ý là refs không phải là thuộc tính bản chất của các component mà chính là của các phần tử React.
Cú pháp cơ bản cho useRef như sau:
import { useRef } from 'react';
function MyComponent() {
const ref = useRef();
return <div ref={ref} />;
}
Một khi ref được liên kết với một phần tử cụ thể, giá trị được lưu trữ trong ref.current
có thể được sử dụng để tương tác trực tiếp với phần tử cơ bản. Ví dụ, giả sử chúng ta muốn focus vào một ô nhập tìm kiếm khi người dùng sử dụng tổ hợp phím Control + K:
import React, { useEffect, useRef } from 'react';
function SearchBar() {
const searchInputRef = useRef();
useEffect(() => {
const handleKeyDown = (event) => {
if (event.ctrlKey && event.key === 'k') {
searchInputRef.current.focus();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, []);
return <input ref={searchInputRef} type='text' />;
}
export default SearchBar;
Trong đoạn mã này, chúng ta sử dụng useRef
để tạo một ref
cho ô nhập tìm kiếm, và useEffect
để thêm một trình xử lý sự kiện cho sự kiện keydown
của window. Khi người dùng nhấn tổ hợp phím Control + K, ô nhập tìm kiếm sẽ được focus.
15. React useContext Hook
Hook useContext của React giúp tối ưu hóa việc sử dụng context so với việc sử dụng thành phần tiêu chuẩn Context.Consumer.
Cú pháp bao gồm việc truyền toàn bộ đối tượng Context mà chúng ta dự định sử dụng vào hàm useContext. Giá trị trả về tương ứng với giá trị được truyền qua Context.
import { useContext } from 'react';
function MyComponent() {
const value = useContext(Context);
// ...
}
// To adapt our previous example using the useContext hook:
import { createContext, useContext } from 'react';
const NameContext = createContext('');
function App() {
return (
<NameContext.Provider value='John Doe'>
<Body />
</NameContext.Provider>
);
}
function Body() {
return <Greeting />;
}
function Greeting() {
const name = useContext(NameContext);
return <h1>Welcome, {name}</h1>;
}
Điều này cho thấy cách useContext đơn giản hóa quá trình truy cập vào các giá trị context, cung cấp một cách tiếp cận ngắn gọn và dễ đọc hơn so với component Context.Consumer truyền thống.
16. React useCallback Hook
Hook useCallback của React là một công cụ quý giá để tối ưu hóa hiệu suất của ứng dụng của chúng ta bằng cách ngăn chặn việc tạo lại các hàm mỗi khi một component được render lại. Điều này rất quan trọng để duy trì hiệu quả trong ứng dụng của chúng ta.
Để minh họa, hãy xem xét ví dụ trước đó của chúng ta với PlayerList. Nếu chúng ta nâng cấp nó để cho phép thêm người chơi vào mảng của chúng ta và truyền xuống một hàm (handleRemovePlayer) thông qua props để xóa người chơi, hàm này sẽ được tạo lại với mỗi lần render lại, có thể ảnh hưởng đến hiệu suất.
Để giải quyết điều này, chúng ta có thể sử dụng useCallback bằng cách đóng gói hàm callback của chúng ta và bao gồm đối số duy nhất của nó - player, trong mảng phụ thuộc (dependencies array).
function App() {
const [player, setPlayer] = React.useState('');
const [players, setPlayers] = React.useState(['Messi', 'Ronaldo', 'Laspada']);
function handleChangeInput(event) {
setPlayer(event.target.value);
}
function handleAddPlayer() {
setPlayers(players.concat(player));
}
const handleRemovePlayer = useCallback(
(player) => {
setPlayers(players.filter((p) => p !== player));
},
[players],
);
return (
<>
<input onChange={handleChangeInput} />
<button onClick={handleAddPlayer}>Add Player</button>
<PlayerList players={players} handleRemovePlayer={handleRemovePlayer} />
</>
);
}
function PlayerList({ players, handleRemovePlayer }) {
return (
<ul>
{players.map((player) => (
<li key={player} onClick={() => handleRemovePlayer(player)}>
{player}
</li>
))}
</ul>
);
}
Trong đoạn mã này, chúng ta sử dụng useCallback
để đảm bảo rằng hàm handleRemovePlayer
không được tạo lại mỗi khi PlayerList
được render lại. Điều này giúp cải thiện hiệu suất của ứng dụng.
17. React useMemo Hook
Chuyển sang useMemo, hook này giúp cải thiện hiệu suất cho phép chúng ta 'memoize' các hoạt động, ghi nhớ kết quả của các phép tính tốn kém để tránh việc tính toán lại không cần thiết.
Trái với useEffect và useCallback, useMemo được thiết kế để trả về một giá trị. Nó đòi hỏi một hàm callback và một mảng phụ thuộc (dependencies array), và callback phải trả về giá trị một cách rõ ràng. Hãy xem xét một ví dụ thực tế từ tài liệu mdx-bundler, chuyển đổi các tệp .mdx thành các component React:
import * as React from 'react';
import { getMDXComponent } from 'mdx-bundler/client';
function Post({ code, frontmatter }) {
const Component = React.useMemo(() => getMDXComponent(code), [code]);
return (
<>
<header>
<h1>{frontmatter.title}</h1>
<p>{frontmatter.description}</p>
</header>
<main>
<Component />
</main>
</>
);
}
Ở đây, useMemo đảm bảo rằng giá trị Component không bị tạo lại không cần thiết trong quá trình render lại, góp phần cải thiện hiệu suất.