Skip to main content

Bài 03-Suy nghĩ trong React

React có thể thay đổi cách bạn nghĩ về các thiết kế bạn nhìn vào và các ứng dụng bạn xây dựng. Khi bạn xây dựng giao diện người dùng bằng React, trước tiên bạn sẽ chia nhỏ nó thành các phần được gọi là thành phần . Sau đó, bạn sẽ mô tả các trạng thái trực quan khác nhau cho từng thành phần của mình. Cuối cùng, bạn sẽ kết nối các thành phần của mình với nhau để dữ liệu chảy qua chúng. Trong hướng dẫn này, chúng tôi sẽ hướng dẫn bạn qua quy trình suy nghĩ về việc xây dựng bảng dữ liệu sản phẩm có thể tìm kiếm bằng React.

Bắt đầu với bản mô phỏng

Hãy tưởng tượng rằng bạn đã có một API JSON và bản thiết kế từ một nhà thiết kế.

API JSON trả về một số dữ liệu trông như thế này:

[
{ category: "Fruits", price: "$1", stocked: true, name: "Apple" },
{ category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
{ category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
{ category: "Vegetables", price: "$2", stocked: true, name: "Spinach" },
{ category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin" },
{ category: "Vegetables", price: "$1", stocked: true, name: "Peas" }
]

Bản mẫu trông như thế này:

Để triển khai UI trong React, bạn thường sẽ thực hiện theo năm bước giống nhau.

Bước 1: Chia giao diện người dùng thành một hệ thống phân cấp thành phần

Bắt đầu bằng cách vẽ các hộp xung quanh mọi thành phần và thành phần phụ trong mô hình và đặt tên cho chúng. Nếu bạn làm việc với một nhà thiết kế, họ có thể đã đặt tên cho các thành phần này trong công cụ thiết kế của họ. Hãy hỏi họ!

Tùy thuộc vào nền tảng của mình, bạn có thể nghĩ đến việc chia nhỏ thiết kế thành các thành phần theo nhiều cách khác nhau:

  • Lập trình —sử dụng cùng các kỹ thuật để quyết định xem bạn có nên tạo một hàm hoặc đối tượng mới hay không. Một trong những kỹ thuật như vậy là nguyên tắc trách nhiệm duy nhất , nghĩa là, một thành phần lý tưởng chỉ nên thực hiện một việc. Nếu nó phát triển, nó nên được phân tách thành các thành phần con nhỏ hơn.
  • CSS — hãy cân nhắc mục đích bạn muốn sử dụng bộ chọn lớp. (Tuy nhiên, các thành phần ít chi tiết hơn một chút.)
  • Thiết kế — hãy cân nhắc cách bạn sẽ sắp xếp các lớp thiết kế.

Nếu JSON của bạn có cấu trúc tốt, bạn thường thấy rằng nó tự nhiên ánh xạ tới cấu trúc thành phần của UI. Đó là vì UI và mô hình dữ liệu thường có cùng kiến ​​trúc thông tin—tức là cùng hình dạng. Phân chia UI của bạn thành các thành phần, trong đó mỗi thành phần khớp với một phần của mô hình dữ liệu của bạn.

Có năm thành phần trên màn hình này:

  1. FilterableProductTable(màu xám) chứa toàn bộ ứng dụng.
  2. SearchBar(màu xanh) tiếp nhận thông tin đầu vào của người dùng.
  3. ProductTable(lavender) hiển thị và lọc danh sách theo thông tin người dùng nhập vào.
  4. ProductCategoryRow(màu xanh lá cây) hiển thị tiêu đề cho mỗi danh mục.
  5. ProductRow (màu vàng) hiển thị một hàng cho mỗi sản phẩm.

Nếu bạn nhìn vào ProductTable(lavender), bạn sẽ thấy rằng tiêu đề bảng (chứa nhãn “Name” và “Price”) không phải là thành phần riêng của nó. Đây là vấn đề sở thích và bạn có thể chọn bất kỳ cách nào. Đối với ví dụ này, nó là một phần của ProductTablevì nó xuất hiện bên trong ProductTabledanh sách 's. Tuy nhiên, nếu tiêu đề này trở nên phức tạp (ví dụ, nếu bạn thêm sắp xếp), bạn có thể di chuyển nó vào thành phần riêng của nó ProductTableHeader.

Bây giờ bạn đã xác định được các thành phần trong mô hình, hãy sắp xếp chúng thành một hệ thống phân cấp. Các thành phần xuất hiện trong một thành phần khác trong mô hình sẽ xuất hiện như một thành phần con trong hệ thống phân cấp:

  • FilterableProductTable
    • SearchBar
    • ProductTable
      • ProductCategoryRow
      • ProductRow

Bước 2: Xây dựng phiên bản tĩnh trong React

Bây giờ bạn đã có hệ thống phân cấp thành phần, đã đến lúc triển khai ứng dụng của bạn. Cách tiếp cận trực tiếp nhất là xây dựng một phiên bản hiển thị UI từ mô hình dữ liệu của bạn mà không cần thêm bất kỳ tương tác nào… nhưng vẫn vậy! Thường thì việc xây dựng phiên bản tĩnh trước rồi thêm tương tác sau sẽ dễ dàng hơn. Xây dựng phiên bản tĩnh đòi hỏi nhiều thao tác nhập và không cần suy nghĩ, nhưng việc thêm tương tác đòi hỏi nhiều thao tác nhập và không cần nhiều thao tác nhập.

Để xây dựng phiên bản tĩnh của ứng dụng hiển thị mô hình dữ liệu của bạn, bạn sẽ muốn xây dựng các thành phần tái sử dụng các thành phần khác và truyền dữ liệu bằng props. Props là một cách truyền dữ liệu từ thành phần cha sang thành phần con. (Nếu bạn quen thuộc với khái niệm trạng thái , đừng sử dụng state để xây dựng phiên bản tĩnh này. State chỉ dành riêng cho tính tương tác, tức là dữ liệu thay đổi theo thời gian. Vì đây là phiên bản tĩnh của ứng dụng, nên bạn không cần nó.)

Bạn có thể xây dựng "từ trên xuống" bằng cách bắt đầu xây dựng các thành phần ở vị trí cao hơn trong hệ thống phân cấp (như FilterableProductTable) hoặc "từ dưới lên" bằng cách làm việc từ các thành phần ở vị trí thấp hơn (như ProductRow). Trong các ví dụ đơn giản hơn, thường dễ dàng hơn khi xây dựng từ trên xuống, và trong các dự án lớn hơn, dễ dàng hơn khi xây dựng từ dưới lên.

function ProductCategoryRow({ category }) {
return (
<tr>
<th colSpan="2">
{category}
</th>
</tr>
);
}

function ProductRow({ product }) {
const name = product.stocked ? product.name :
<span style={{ color: 'red' }}>
{product.name}
</span>;

return (
<tr>
<td>{name}</td>
<td>{product.price}</td>
</tr>
);
}

function ProductTable({ products }) {
const rows = [];
let lastCategory = null;

products.forEach((product) => {
if (product.category !== lastCategory) {
rows.push(
<ProductCategoryRow
category={product.category}
key={product.category} />
);
}
rows.push(
<ProductRow
product={product}
key={product.name} />
);
lastCategory = product.category;
});

return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}

function SearchBar() {
return (
<form>
<input type="text" placeholder="Search..." />
<label>
<input type="checkbox" />
{' '}
Only show products in stock
</label>
</form>
);
}

function FilterableProductTable({ products }) {
return (
<div>
<SearchBar />
<ProductTable products={products} />
</div>
);
}

const PRODUCTS = [
{category: "Fruits", price: "$1", stocked: true, name: "Apple"},
{category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit"},
{category: "Fruits", price: "$2", stocked: false, name: "Passionfruit"},
{category: "Vegetables", price: "$2", stocked: true, name: "Spinach"},
{category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin"},
{category: "Vegetables", price: "$1", stocked: true, name: "Peas"}
];

export default function App() {
return <FilterableProductTable products={PRODUCTS} />;
}

(Nếu mã này có vẻ khó hiểu, hãy xem qua phần Bắt đầu nhanh trước!)

Sau khi xây dựng các thành phần của bạn, bạn sẽ có một thư viện các thành phần có thể tái sử dụng để hiển thị mô hình dữ liệu của bạn. Vì đây là một ứng dụng tĩnh, các thành phần sẽ chỉ trả về JSX. Thành phần ở đầu phân cấp ( FilterableProductTable) sẽ lấy mô hình dữ liệu của bạn làm prop. Đây được gọi là luồng dữ liệu một chiều vì dữ liệu chảy xuống từ thành phần cấp cao nhất đến các thành phần ở dưới cùng của cây.

Cạm bẫy

Tại thời điểm này, bạn không nên sử dụng bất kỳ giá trị trạng thái nào. Đó là bước tiếp theo!

Bước 3: Tìm biểu diễn tối thiểu nhưng đầy đủ của trạng thái UI

Để làm cho UI tương tác, bạn cần cho phép người dùng thay đổi mô hình dữ liệu cơ bản của bạn. Bạn sẽ sử dụng trạng thái cho việc này.

Hãy nghĩ về trạng thái như là tập dữ liệu thay đổi tối thiểu mà ứng dụng của bạn cần nhớ. Nguyên tắc quan trọng nhất để cấu trúc trạng thái là giữ cho nó DRY (Đừng lặp lại chính mình). Tìm ra biểu diễn tối thiểu tuyệt đối của trạng thái mà ứng dụng của bạn cần và tính toán mọi thứ khác theo yêu cầu. Ví dụ, nếu bạn đang xây dựng danh sách mua sắm, bạn có thể lưu trữ các mục dưới dạng một mảng trong trạng thái. Nếu bạn cũng muốn hiển thị số lượng mục trong danh sách, đừng lưu trữ số lượng mục dưới dạng một giá trị trạng thái khác—thay vào đó, hãy đọc độ dài của mảng.

Bây giờ hãy nghĩ đến tất cả các phần dữ liệu trong ứng dụng ví dụ này:

  1. Danh sách sản phẩm ban đầu
  2. Văn bản tìm kiếm người dùng đã nhập
  3. Giá trị của hộp kiểm
  4. Danh sách sản phẩm đã lọc

Trong số những điều sau đây, điều nào là trạng thái? Xác định những điều nào không phải là trạng thái:

  • Nó có không thay đổi theo thời gian không? Nếu có thì nó không phải là trạng thái.
  • Nó có được truyền từ phần tử cha qua props không? Nếu có thì nó không phải là trạng thái.
  • Bạn có thể tính toán nó dựa trên trạng thái hoặc props hiện có trong thành phần của bạn không? Nếu có, thì chắc chắn nó không phải là trạng thái!

Những gì còn lại có lẽ là trạng thái.

Chúng ta hãy cùng xem xét lại từng cái một:

  1. Danh sách sản phẩm ban đầu được truyền vào dưới dạng props, vì vậy nó không phải là trạng thái.
  2. Văn bản tìm kiếm có vẻ như là trạng thái vì nó thay đổi theo thời gian và không thể tính toán được từ bất cứ thứ gì.
  3. Giá trị của hộp kiểm có vẻ là trạng thái vì nó thay đổi theo thời gian và không thể tính toán được từ bất cứ thứ gì.
  4. Danh sách sản phẩm đã lọc không phải là trạng thái vì nó có thể được tính toán bằng cách lấy danh sách sản phẩm gốc và lọc theo văn bản tìm kiếm và giá trị của hộp kiểm.

Điều này có nghĩa là chỉ có văn bản tìm kiếm và giá trị của hộp kiểm là trạng thái! Làm tốt lắm!

Lặn sâu

Đạo cụ so với Nhà nước

Hiển thị chi tiết

Bước 4: Xác định tiểu bang của bạn nên sống ở đâu

Sau khi xác định dữ liệu trạng thái tối thiểu của ứng dụng, bạn cần xác định thành phần nào chịu trách nhiệm thay đổi trạng thái này hoặc sở hữu trạng thái. Hãy nhớ: React sử dụng luồng dữ liệu một chiều, truyền dữ liệu xuống hệ thống phân cấp thành phần từ thành phần cha sang thành phần con. Có thể không rõ ngay thành phần nào nên sở hữu trạng thái nào. Điều này có thể khó khăn nếu bạn mới làm quen với khái niệm này, nhưng bạn có thể tìm ra bằng cách làm theo các bước sau!

Đối với mỗi tiểu bang trong đơn đăng ký của bạn:

  1. Xác định mọi thành phần hiển thị thứ gì đó dựa trên trạng thái đó.
  2. Tìm thành phần cha chung gần nhất của chúng—một thành phần đứng trên tất cả chúng trong hệ thống phân cấp.
  3. Quyết định nơi mà nhà nước nên sinh sống:
    1. Thông thường, bạn có thể đưa trạng thái trực tiếp vào trạng thái cha chung của chúng.
    2. Bạn cũng có thể đưa trạng thái vào một số thành phần phía trên thành phần cha chung của chúng.
    3. Nếu bạn không thể tìm thấy thành phần nào có ý nghĩa sở hữu trạng thái, hãy tạo một thành phần mới chỉ để lưu giữ trạng thái và thêm nó vào đâu đó trong hệ thống phân cấp phía trên thành phần cha chung.

Ở bước trước, bạn đã tìm thấy hai phần trạng thái trong ứng dụng này: văn bản nhập tìm kiếm và giá trị của hộp kiểm. Trong ví dụ này, chúng luôn xuất hiện cùng nhau, do đó, việc đặt chúng vào cùng một vị trí là hợp lý.

Bây giờ chúng ta hãy xem xét chiến lược của chúng tôi dành cho họ:

  1. Xác định các thành phần sử dụng trạng thái:
    • ProductTablecần lọc danh sách sản phẩm dựa trên trạng thái đó (văn bản tìm kiếm và giá trị hộp kiểm).
    • SearchBarcần hiển thị trạng thái đó (văn bản tìm kiếm và giá trị hộp kiểm).
  2. Tìm thành phần cha chung của chúng: Thành phần cha đầu tiên mà cả hai thành phần chia sẻ là FilterableProductTable.
  3. Quyết định trạng thái nằm ở đâu : Chúng tôi sẽ giữ văn bản bộ lọc và các giá trị trạng thái đã kiểm tra trong FilterableProductTable.

Vì vậy, các giá trị của nhà nước sẽ tồn tại FilterableProductTable.

Thêm trạng thái vào thành phần bằng useState()Hook. Hook là các hàm đặc biệt cho phép bạn "móc vào" React. Thêm hai biến trạng thái ở đầu FilterableProductTablevà chỉ định trạng thái ban đầu của chúng:

function FilterableProductTable({ products }) {
const [filterText, setFilterText] = useState('');
const [inStockOnly, setInStockOnly] = useState(false);

Sau đó, truyền filterTextinStockOnlytới ProductTableSearchBarnhư đạo cụ:

<div>
<SearchBar
filterText={filterText}
inStockOnly={inStockOnly} />
<ProductTable
products={products}
filterText={filterText}
inStockOnly={inStockOnly} />
</div>

Bạn có thể bắt đầu xem ứng dụng của mình sẽ hoạt động như thế nào. Chỉnh sửa filterTextgiá trị ban đầu từ useState('')đến useState('fruit')trong mã hộp cát bên dưới. Bạn sẽ thấy cả văn bản nhập tìm kiếm và bản cập nhật bảng:

import { useState } from 'react';

function FilterableProductTable({ products }) {
const [filterText, setFilterText] = useState('');
const [inStockOnly, setInStockOnly] = useState(false);

return (
<div>
<SearchBar
filterText={filterText}
inStockOnly={inStockOnly} />
<ProductTable
products={products}
filterText={filterText}
inStockOnly={inStockOnly} />
</div>
);
}

function ProductCategoryRow({ category }) {
return (
<tr>
<th colSpan="2">
{category}
</th>
</tr>
);
}

function ProductRow({ product }) {
const name = product.stocked ? product.name :
<span style={{ color: 'red' }}>
{product.name}
</span>;

return (
<tr>
<td>{name}</td>
<td>{product.price}</td>
</tr>
);
}

function ProductTable({ products, filterText, inStockOnly }) {
const rows = [];
let lastCategory = null;

products.forEach((product) => {
if (
product.name.toLowerCase().indexOf(
filterText.toLowerCase()
) === -1
) {
return;
}
if (inStockOnly && !product.stocked) {
return;
}
if (product.category !== lastCategory) {
rows.push(
<ProductCategoryRow
category={product.category}
key={product.category} />
);
}
rows.push(
<ProductRow
product={product}
key={product.name} />
);
lastCategory = product.category;
});

return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}

function SearchBar({ filterText, inStockOnly }) {
return (
<form>
<input
type="text"
value={filterText}
placeholder="Search..."/>
<label>
<input
type="checkbox"
checked={inStockOnly} />
{' '}
Only show products in stock
</label>
</form>
);
}

const PRODUCTS = [
{category: "Fruits", price: "$1", stocked: true, name: "Apple"},
{category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit"},
{category: "Fruits", price: "$2", stocked: false, name: "Passionfruit"},
{category: "Vegetables", price: "$2", stocked: true, name: "Spinach"},
{category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin"},
{category: "Vegetables", price: "$1", stocked: true, name: "Peas"}
];

export default function App() {
return <FilterableProductTable products={PRODUCTS} />;
}

Cảnh báo: Bạn đã cung cấp prop value cho trường biểu mẫu mà không có trình xử lý onChange. Điều này sẽ hiển thị trường chỉ đọc. Nếu trường có thể thay đổi, hãy sử dụng defaultValue. Nếu không, hãy đặt onChange hoặc readOnly. tại đầu vào tại biểu mẫu tại SearchBar (https://786946de.sandpack-bundler-4bw.pages.dev/src/App.js:120:5) tại div tại FilterableProductTable (https://786946de.sandpack-bundler-4bw.pages.dev/src/App.js:18:5) tại App

Cảnh báo: Bạn đã cung cấp prop checked cho một trường biểu mẫu mà không có trình xử lý onChange. Điều này sẽ hiển thị một trường chỉ đọc. Nếu trường có thể thay đổi, hãy sử dụng defaultChecked. Nếu không, hãy đặt onChange hoặc readOnly. tại đầu vào tại nhãn tại biểu mẫu tại SearchBar (https://786946de.sandpack-bundler-4bw.pages.dev/src/App.js:120:5) tại div tại FilterableProductTable (https://786946de.sandpack-bundler-4bw.pages.dev/src/App.js:18:5) tại App

Hiển thị thêm

Lưu ý rằng việc chỉnh sửa biểu mẫu vẫn chưa hoạt động. Có một lỗi bảng điều khiển trong hộp cát ở trên giải thích lý do tại sao:

Console

You provided a value prop to a form field without an onChange handler. This will render a read-only field.

Trong hộp cát ở trên, ProductTablehãy SearchBarđọc filterTextinStockOnlyprops để hiển thị bảng, đầu vào và hộp kiểm. Ví dụ, đây là cách SearchBarđiền giá trị đầu vào:

function SearchBar({ filterText, inStockOnly }) {
return (
<form>
<input
type="text"
value={filterText}
placeholder="Search..."/>

Tuy nhiên, bạn vẫn chưa thêm bất kỳ mã nào để phản hồi hành động của người dùng như nhập liệu. Đây sẽ là bước cuối cùng của bạn.

Bước 5: Thêm luồng dữ liệu ngược

Hiện tại ứng dụng của bạn hiển thị đúng với props và state chảy xuống hệ thống phân cấp. Nhưng để thay đổi trạng thái theo đầu vào của người dùng, bạn sẽ cần hỗ trợ dữ liệu chảy theo cách khác: các thành phần biểu mẫu sâu trong hệ thống phân cấp cần cập nhật trạng thái trong FilterableProductTable.

React làm cho luồng dữ liệu này trở nên rõ ràng, nhưng nó đòi hỏi nhiều thao tác gõ hơn so với ràng buộc dữ liệu hai chiều. Nếu bạn thử gõ hoặc đánh dấu vào ô trong ví dụ trên, bạn sẽ thấy React bỏ qua dữ liệu đầu vào của bạn. Đây là cố ý. Bằng cách viết <input value={filterText} />, bạn đã đặt valueprop của the inputluôn bằng với filterTexttrạng thái được truyền vào từ FilterableProductTable. Vì filterTexttrạng thái không bao giờ được đặt, nên dữ liệu đầu vào không bao giờ thay đổi.

Bạn muốn làm cho bất cứ khi nào người dùng thay đổi các đầu vào biểu mẫu, trạng thái sẽ cập nhật để phản ánh những thay đổi đó. Trạng thái thuộc sở hữu của FilterableProductTable, vì vậy chỉ có thể gọi setFilterTextsetInStockOnly. Để SearchBarcập nhật FilterableProductTabletrạng thái 's, bạn cần truyền các hàm này xuống SearchBar:

function FilterableProductTable({ products }) {
const [filterText, setFilterText] = useState('');
const [inStockOnly, setInStockOnly] = useState(false);

return (
<div>
<SearchBar
filterText={filterText}
inStockOnly={inStockOnly}
onFilterTextChange={setFilterText}
onInStockOnlyChange={setInStockOnly} />

Bên trong SearchBar, bạn sẽ thêm onChangetrình xử lý sự kiện và thiết lập trạng thái cha từ chúng:

function SearchBar({
filterText,
inStockOnly,
onFilterTextChange,
onInStockOnlyChange
}) {
return (
<form>
<input
type="text"
value={filterText}
placeholder="Search..."
onChange={(e) => onFilterTextChange(e.target.value)}
/>
<label>
<input
type="checkbox"
checked={inStockOnly}
onChange={(e) => onInStockOnlyChange(e.target.checked)}

Bây giờ ứng dụng đã hoạt động hoàn toàn!

import { useState } from 'react';

function FilterableProductTable({ products }) {
const [filterText, setFilterText] = useState('');
const [inStockOnly, setInStockOnly] = useState(false);

return (
<div>
<SearchBar
filterText={filterText}
inStockOnly={inStockOnly}
onFilterTextChange={setFilterText}
onInStockOnlyChange={setInStockOnly} />
<ProductTable
products={products}
filterText={filterText}
inStockOnly={inStockOnly} />
</div>
);
}

function ProductCategoryRow({ category }) {
return (
<tr>
<th colSpan="2">
{category}
</th>
</tr>
);
}

function ProductRow({ product }) {
const name = product.stocked ? product.name :
<span style={{ color: 'red' }}>
{product.name}
</span>;

return (
<tr>
<td>{name}</td>
<td>{product.price}</td>
</tr>
);
}

function ProductTable({ products, filterText, inStockOnly }) {
const rows = [];
let lastCategory = null;

products.forEach((product) => {
if (
product.name.toLowerCase().indexOf(
filterText.toLowerCase()
) === -1
) {
return;
}
if (inStockOnly && !product.stocked) {
return;
}
if (product.category !== lastCategory) {
rows.push(
<ProductCategoryRow
category={product.category}
key={product.category} />
);
}
rows.push(
<ProductRow
product={product}
key={product.name} />
);
lastCategory = product.category;
});

return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}

function SearchBar({
filterText,
inStockOnly,
onFilterTextChange,
onInStockOnlyChange
}) {
return (
<form>
<input
type="text"
value={filterText} placeholder="Search..."
onChange={(e) => onFilterTextChange(e.target.value)} />
<label>
<input
type="checkbox"
checked={inStockOnly}
onChange={(e) => onInStockOnlyChange(e.target.checked)} />
{' '}
Only show products in stock
</label>
</form>
);
}

const PRODUCTS = [
{category: "Fruits", price: "$1", stocked: true, name: "Apple"},
{category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit"},
{category: "Fruits", price: "$2", stocked: false, name: "Passionfruit"},
{category: "Vegetables", price: "$2", stocked: true, name: "Spinach"},
{category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin"},
{category: "Vegetables", price: "$1", stocked: true, name: "Peas"}
];

export default function App() {
return <FilterableProductTable products={PRODUCTS} />;
}

Bạn có thể tìm hiểu tất cả về cách xử lý sự kiện và cập nhật trạng thái trong phần Thêm tính tương tác .

Đi đâu từ đây

Đây là phần giới thiệu rất ngắn gọn về cách suy nghĩ về việc xây dựng các thành phần và ứng dụng với React. Bạn có thể bắt đầu một dự án React ngay bây giờ hoặc tìm hiểu sâu hơn về tất cả các cú pháp được sử dụng trong hướng dẫn này.