Skip to main content

01-React

Bạn sẽ học được

  • Cách tạo và lồng các thành phần
  • Cách thêm đánh dấu và kiểu
  • Cách hiển thị dữ liệu
  • Cách hiển thị điều kiện và danh sách
  • Cách phản hồi sự kiện và cập nhật màn hình
  • Cách chia sẻ dữ liệu giữa các thành phần

Tạo và lồng các thành phần

Ứng dụng React được tạo thành từ các thành phần . Thành phần là một phần của UI (giao diện người dùng) có logic và giao diện riêng. Một thành phần có thể nhỏ như một nút hoặc lớn như toàn bộ một trang.

Các thành phần React là các hàm JavaScript trả về mã đánh dấu:

function MyButton() {
return (
<button>I'm a button</button>
);
}

Bây giờ bạn đã khai báo MyButton, bạn có thể lồng nó vào một thành phần khác:

export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}

Lưu ý rằng <MyButton />bắt đầu bằng chữ in hoa. Đó là cách bạn biết đó là thành phần React. Tên thành phần React phải luôn bắt đầu bằng chữ in hoa, trong khi thẻ HTML phải viết thường.

Hãy xem kết quả:

function MyButton() {
return (
<button>
I'm a button
</button>
);
}

export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}

Từ export defaultkhóa chỉ định thành phần chính trong tệp. Nếu bạn không quen với một số cú pháp JavaScript, MDNjavascript.info có tài liệu tham khảo tuyệt vời.

Viết đánh dấu bằng JSX

Cú pháp đánh dấu mà bạn thấy ở trên được gọi là JSX . Nó là tùy chọn, nhưng hầu hết các dự án React đều sử dụng JSX vì sự tiện lợi của nó. Tất cả các công cụ chúng tôi đề xuất để phát triển cục bộ đều hỗ trợ JSX ngay từ đầu.

JSX chặt chẽ hơn HTML. Bạn phải đóng các thẻ như <br />. Thành phần của bạn cũng không thể trả về nhiều thẻ JSX. Bạn phải gói chúng vào một phần tử cha chung, như a <div>...</div>hoặc một <>...</>wrapper rỗng:

function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}```

Nếu bạn có nhiều HTML cần chuyển sang JSX, bạn có thể sử dụng [trình chuyển đổi trực tuyến.](https://transform.tools/html-to-jsx)

## Thêm kiểu dáng[](https://react.dev/learn#adding-styles "Liên kết để thêm kiểu")

Trong React, bạn chỉ định một lớp CSS với
className

Nó hoạt động theo cùng một cách như thuộc tính HTML

class:

<img className="avatar" />

Sau đó, bạn viết các quy tắc CSS cho nó trong một tệp CSS riêng:

/* In your CSS */
.avatar {
border-radius: 50%;
}

React không quy định cách bạn thêm tệp CSS. Trong trường hợp đơn giản nhất, bạn sẽ thêm thẻ <link>vào HTML của mình. Nếu bạn sử dụng công cụ xây dựng hoặc khung, hãy tham khảo tài liệu của công cụ đó để tìm hiểu cách thêm tệp CSS vào dự án của bạn.

Hiển thị dữ liệu

JSX cho phép bạn đưa markup vào JavaScript. Dấu ngoặc nhọn cho phép bạn "thoát trở lại" vào JavaScript để bạn có thể nhúng một số biến từ mã của mình và hiển thị cho người dùng. Ví dụ, điều này sẽ hiển thị user.name:

return (
<h1>
{user.name}
</h1>
);

Bạn cũng có thể "thoát vào JavaScript" từ các thuộc tính JSX, nhưng bạn phải sử dụng dấu ngoặc nhọn thay vì dấu ngoặc kép. Ví dụ, className="avatar"truyền "avatar"chuỗi dưới dạng lớp CSS, nhưng src={user.imageUrl}đọc giá trị biến JavaScript user.imageUrl, sau đó truyền giá trị đó dưới dạng srcthuộc tính:

return (  

<img

className="avatar"

src={user.imageUrl}

/>

);

Bạn cũng có thể đặt các biểu thức phức tạp hơn bên trong dấu ngoặc nhọn JSX, ví dụ, nối chuỗi :

const user = {
name: 'Hedy Lamarr',
imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
imageSize: 90,
};

export default function Profile() {
return (
<>
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'Photo of ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize
}}
/>
</>
);
}


Trong ví dụ trên, style={{}}không phải là cú pháp đặc biệt mà là một {}đối tượng thông thường bên trong style={ }dấu ngoặc nhọn JSX. Bạn có thể sử dụng stylethuộc tính khi kiểu của bạn phụ thuộc vào các biến JavaScript.

Hiển thị có điều kiện

Trong React, không có cú pháp đặc biệt nào để viết điều kiện. Thay vào đó, bạn sẽ sử dụng các kỹ thuật tương tự như khi viết mã JavaScript thông thường. Ví dụ, bạn có thể sử dụng một ifcâu lệnh để bao gồm JSX có điều kiện:

let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);

Nếu bạn thích mã nhỏ gọn hơn, bạn có thể sử dụng toán tử điều kiện ?. Không giống như if, nó hoạt động bên trong JSX:

<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>

Khi bạn không cần elsenhánh, bạn cũng có thể sử dụng cú pháp logic&& ngắn hơn :

<div>
{isLoggedIn && <AdminPanel />}
</div>

Tất cả các cách tiếp cận này cũng có tác dụng đối với việc chỉ định thuộc tính có điều kiện. Nếu bạn không quen với một số cú pháp JavaScript này, bạn có thể bắt đầu bằng cách luôn sử dụng if...else.

Hiển thị danh sách

Bạn sẽ dựa vào các tính năng của JavaScript như forvòng lặphàm mảngmap() để hiển thị danh sách các thành phần.

Ví dụ, giả sử bạn có một mảng sản phẩm:

const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];

Bên trong thành phần của bạn, hãy sử dụng map()hàm để chuyển đổi một mảng sản phẩm thành một mảng <li>mặt hàng:

const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);

return (
<ul>{listItems}</ul>
);

Lưu ý cách <li>có một keythuộc tính. Đối với mỗi mục trong danh sách, bạn nên truyền một chuỗi hoặc một số để xác định duy nhất mục đó trong số các mục anh chị em của nó. Thông thường, một khóa phải đến từ dữ liệu của bạn, chẳng hạn như ID cơ sở dữ liệu. React sử dụng các khóa của bạn để biết điều gì đã xảy ra nếu sau này bạn chèn, xóa hoặc sắp xếp lại các mục.

const products = [
{ title: 'Cabbage', isFruit: false, id: 1 },
{ title: 'Garlic', isFruit: false, id: 2 },
{ title: 'Apple', isFruit: true, id: 3 },
];

export default function ShoppingList() {
const listItems = products.map(product =>
<li
key={product.id}
style={{
color: product.isFruit ? 'magenta' : 'darkgreen'
}}
>
{product.title}
</li>
);

return (
<ul>{listItems}</ul>
);
}

Phản hồi các sự kiện

Bạn có thể phản hồi các sự kiện bằng cách khai báo các hàm xử lý sự kiện bên trong các thành phần của mình:

function MyButton() {
function handleClick() {
alert('You clicked me!');
}

return (
<button onClick={handleClick}>
Click me
</button>
);
}

Lưu ý onClick={handleClick}không có dấu ngoặc đơn ở cuối! Không gọi hàm xử lý sự kiện: bạn chỉ cần truyền nó xuống . React sẽ gọi trình xử lý sự kiện của bạn khi người dùng nhấp vào nút.

Đang cập nhật màn hình

Thông thường, bạn sẽ muốn thành phần của mình "ghi nhớ" một số thông tin và hiển thị thông tin đó. Ví dụ, có thể bạn muốn đếm số lần nhấp vào nút. Để thực hiện việc này, hãy thêm trạng thái vào thành phần của bạn.

Đầu tiên, nhập useStatetừ React:

import { useState } from 'react';

Bây giờ bạn có thể khai báo một biến trạng thái bên trong thành phần của mình:

function MyButton() {
const [count, setCount] = useState(0);
// ...

Bạn sẽ nhận được hai thứ từ useState: trạng thái hiện tại ( count), và hàm cho phép bạn cập nhật trạng thái đó ( setCount). Bạn có thể đặt cho chúng bất kỳ tên nào, nhưng theo quy ước thì phải viết [something, setSomething].

Lần đầu tiên nút được hiển thị, countsẽ là 0do bạn đã truyền 0đến useState(). Khi bạn muốn thay đổi trạng thái, hãy gọi setCount()và truyền giá trị mới cho nó. Nhấp vào nút này sẽ tăng bộ đếm:

function MyButton() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}

React sẽ gọi lại hàm thành phần của bạn. Lần này, countsẽ là 1. Sau đó sẽ là 2. Và cứ tiếp tục như vậy.

Nếu bạn render cùng một thành phần nhiều lần, mỗi thành phần sẽ có trạng thái riêng. Nhấp vào từng nút riêng biệt:

import { useState } from 'react';

export default function MyApp() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}

function MyButton() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}

Lưu ý cách mỗi nút “ghi nhớ” counttrạng thái của riêng nó và không ảnh hưởng đến các nút khác.

Sử dụng Hooks

Các hàm bắt đầu bằng useđược gọi là Hooks . useStatelà Hook tích hợp do React cung cấp. Bạn có thể tìm thấy các Hook tích hợp khác trong tài liệu tham khảo API. Bạn cũng có thể viết Hook của riêng mình bằng cách kết hợp các Hook hiện có.

Hooks hạn chế hơn các hàm khác. Bạn chỉ có thể gọi Hooks ở đầu các thành phần của mình (hoặc các Hooks khác). Nếu bạn muốn sử dụng useStatetrong một điều kiện hoặc một vòng lặp, hãy trích xuất một thành phần mới và đặt nó ở đó.

Chia sẻ dữ liệu giữa các thành phần

Trong ví dụ trước, mỗi mục đều MyButtoncó giá trị độc lập countvà khi mỗi nút được nhấp, chỉ có giá counttrị của nút được nhấp thay đổi:

Sơ đồ cho thấy một cây gồm ba thành phần, một thành phần cha được gắn nhãn MyApp và hai thành phần con được gắn nhãn MyButton. Cả hai thành phần MyButton đều chứa một số đếm có giá trị bằng không.

Ban đầu, trạng thái MyButtoncủa mỗi người count0

Sơ đồ giống như sơ đồ trước, với số lượng thành phần MyButton con đầu tiên được tô sáng cho biết một lần nhấp với giá trị số lượng tăng lên một. Thành phần MyButton thứ hai vẫn chứa giá trị bằng không.

MyButtonBản cập nhật đầu tiên của nó count1

Tuy nhiên, bạn thường cần các thành phần để chia sẻ dữ liệu và luôn cập nhật cùng nhau .

Để cả hai MyButtonthành phần hiển thị giống nhau countvà cập nhật cùng nhau, bạn cần di chuyển trạng thái từ các nút riêng lẻ "lên trên" đến thành phần gần nhất chứa tất cả các nút đó.

Trong ví dụ này, nó là MyApp:

Sơ đồ cho thấy một cây gồm ba thành phần, một thành phần cha được gắn nhãn MyApp và hai thành phần con được gắn nhãn MyButton. MyApp chứa giá trị đếm bằng không được truyền xuống cả hai thành phần MyButton, cũng hiển thị giá trị bằng không.

Ban đầu, trạng thái MyAppcủa ' count0và được truyền lại cho cả hai đứa con

Sơ đồ giống như sơ đồ trước, với số lượng thành phần MyApp cha được tô sáng cho biết một cú nhấp chuột với giá trị tăng lên một. Luồng đến cả hai thành phần MyButton con cũng được tô sáng và giá trị số lượng trong mỗi thành phần con được đặt thành một cho biết giá trị đã được truyền xuống.

Khi nhấp, cập nhật trạng thái MyAppcủa nó và truyền xuống cho cả hai phần tử concount``1

Bây giờ khi bạn nhấp vào bất kỳ nút nào, countin MyAppsẽ thay đổi, điều này sẽ thay đổi cả hai số đếm trong MyButton. Sau đây là cách bạn có thể thể hiện điều này trong mã.

Đầu tiên, di chuyển trạng thái lên từ MyButtonvào MyApp:

export default function MyApp() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}

function MyButton() {
// ... we're moving code from here ...
}

Sau đó, truyền trạng thái xuống từ MyAppđến từng MyButton, cùng với trình xử lý nhấp chuột được chia sẻ. Bạn có thể truyền thông tin đến MyButtonbằng cách sử dụng dấu ngoặc nhọn JSX, giống như bạn đã làm trước đó với các thẻ tích hợp như <img>:

export default function MyApp() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}

Thông tin bạn truyền xuống như thế này được gọi là props . Bây giờ MyAppthành phần chứa counttrạng thái và handleClicktrình xử lý sự kiện, và truyền cả hai xuống dưới dạng props cho mỗi nút.

Cuối cùng, hãy thay đổi MyButtonđể đọc các thuộc tính bạn đã truyền từ thành phần cha của nó:

function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}

Khi bạn nhấp vào nút, onClicktrình xử lý sẽ kích hoạt. Prop của mỗi nút onClickđược đặt thành handleClickhàm bên trong MyApp, do đó mã bên trong nút chạy. Mã đó gọi setCount(count + 1), tăng countbiến trạng thái. countGiá trị mới được truyền dưới dạng prop cho mỗi nút, do đó tất cả chúng đều hiển thị giá trị mới. Điều này được gọi là "nâng trạng thái lên". Bằng cách di chuyển trạng thái lên, bạn đã chia sẻ nó giữa các thành phần.

import { useState } from 'react';

export default function MyApp() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}

function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);

Các bước tiếp theo

Bây giờ, bạn đã biết những điều cơ bản về cách viết mã React!

Hãy xem Hướng dẫn để áp dụng vào thực tế và xây dựng ứng dụng nhỏ đầu tiên của bạn bằng React.

Source: https://react.dev/learn