Sử dụng trạng thái yêu cầu trong Redux
Ở các bài học trước, chúng ta đã sử dụng các reducer bổ sung để mô tả ứng dụng của mình nên làm gì nếu fetchProducts gửi các action pending, fulfilled và rejected khi yêu cầu. Bây giờ chúng ta có thể hiển thị cho người dùng giai đoạn hiện tại của việc tải dữ liệu.
Hãy mở ứng dụng sản phẩm của chúng ta, và trong đó là tệp ProductsList.jsx. Điều đầu tiên chúng ta sẽ làm là tạo một component riêng cho thẻ sản phẩm ProductCard. Hãy làm điều này ngay sau các dòng nhập khẩu trước hàm ProductsList. Chúng ta sẽ truyền product cho nó dưới dạng prop:
const ProductCard = ({ product }) => {
return ()
}
Và bây giờ, trong dấu ngoặc tròn trống của return, hãy chuyển toàn bộ mã để hiển thị dữ liệu sản phẩm từ dispProducts:
const ProductCard = ({ product }) => {
return (
<div key={product.id} className="product-excerpt">
<h3>{product.name}</h3>
<SellerOfProd sellerId={product.seller} />
<p>{product.desc.substring(0, 100)}</p>
<UserReactions product={product} />
<Link to={`/products/${product.id}`} className="link-btn">
view
</Link>
</div>
)
}
Và xóa dòng mã còn lại trong ProductsList. Nó không cần thiết nữa:
const dispProducts = products.map((product) => ())
Và bây giờ, ở đầu mã của hàm ProductsList, hãy tạo thêm một vài biến, error và content. Biến đầu tiên sẽ dành cho lỗi, biến thứ hai chúng ta sẽ ghi nội dung này hay nội dung khác tùy thuộc vào trạng thái yêu cầu. Hãy làm điều này trước const dataFetch = useRef(false):
const error = useSelector((state) => state.products.error)
let content
Bây giờ, trước lệnh return của component ProductsList, hãy viết một khối mã với các điều kiện, theo đó content sẽ được ghi nội dung này hay nội dung khác tùy thuộc vào trạng thái. Đầu tiên chúng ta sẽ mô tả trạng thái 'in progress' - khi yêu cầu của chúng ta được gửi đi. Trong trường hợp này, chúng ta sẽ thông báo cho người dùng rằng dữ liệu đang được tải:
if (productStatus === 'in progress') {
content = <p>Products list loading ...</p>
}
Nếu việc tải của chúng ta thành công (chúng ta đã đánh dấu điều này là 'success'), thì chúng ta cần hiển thị danh sách sản phẩm nhận được. Hãy hiển thị nó trong map bằng component ProductCard, mà chúng ta sẽ truyền product dưới dạng prop:
if (productStatus === 'in progress') {
content = <p>Products list loading ...</p>
} else if (productStatus === 'success') {
content = products.map((product) => (
<ProductCard key={product.id} product={product} />
))
}
Và trạng thái cuối cùng mà chúng ta có - là 'fail'. Hãy thêm nó. Ở đây chúng ta sử dụng biến error, mà chúng ta đã ghi lỗi từ state vào ở trên:
if (productStatus === 'in progress') {
content = <p>Products list loading ...</p>
} else if (productStatus === 'success') {
content = products.map((product) => (
<ProductCard key={product.id} product={product} />
))
} else if (productStatus === 'fail') {
content = <div>{error}</div>
}
Và bước cuối cùng, trong khối mã cho return, chúng ta thay thế {dispProducts} cũ bằng {content}.
Hãy khởi chạy ứng dụng của chúng ta, nhấp vào 'Products' trong menu. Mọi thứ đều hoạt động. Chúng ta thấy rằng khoảng 2 giây (như chúng ta đã đặt trên máy chủ) dòng chữ 'Products list loading ...' treo dưới biểu mẫu thêm sản phẩm, và sau đó danh sách sản phẩm xuất hiện.
Hãy mở ứng dụng sinh viên của bạn. Mở tệp StudentsList.jsx trong đó. Tạo một component mới StudentCard trong đó. Chuyển mã từ dispStudents vào nó, như được hiển thị trong bài học.
Tạo các biến error và content trong hàm StudentsList. Gán nội dung cho biến content tùy thuộc vào trạng thái yêu cầu. Đừng quên thay thế dispStudents cũ bằng content trong mã HTML được trả về.