Next.js & Redux Toolkit (Phần 4): Xây Dựng Hệ Thống Giỏ Hàng Chuyên Nghiệp
Chào các bạn, ở 3 phần trước chúng ta đã biết cách lấy và hiển thị dữ liệu. Tuy nhiên, một vấn đề nảy sinh: Làm sao để dữ liệu giỏ hàng "đi theo" người dùng từ trang này sang trang khác? Câu trả lời chính là Redux Toolkit – công cụ quản lý State tập trung mạnh mẽ nhất hiện nay cho React/Next.js.
Câu 1: Thiết Lập Redux Store Cho Giỏ Hàng
Để bắt đầu, chúng ta cần cài đặt các thư viện cần thiết:
npm install @reduxjs/toolkit react-redux
1. Định nghĩa Slice (cartslice.js) Slice là nơi chứa Logic của giỏ hàng (thêm, xóa, sửa số lượng). Tại đây, chúng ta xử lý việc kiểm tra sản phẩm đã tồn tại hay chưa để cộng dồn số lượng thay vì thêm mới.
2. Tạo Store và Provider
Chúng ta bọc toàn bộ ứng dụng (layout.js) trong một Provider. Điều này cho phép bất kỳ Component con nào (như Header hay DetailPage) cũng có thể truy cập vào dữ liệu giỏ hàng.
Lưu ý quan trọng về Client Component: Vì Redux yêu cầu tương tác phía Client, file Provider.js phải có directive "use client".
Câu 2: Đồng Bộ Số Lượng Trên Icon Giỏ Hàng
Một trải nghiệm người dùng tốt là phải thấy được số lượng sản phẩm thay đổi ngay lập tức trên Header khi nhấn nút "Thêm".
Chúng ta sử dụng useSelector để lấy danh sách items từ Redux Store và dùng hàm .reduce() để tính tổng số lượng (quantity):
const cartItems = useSelector((state) => state.cart.items);
const cartCount = cartItems.reduce((count, item) => count + Number(item.quantity), 0);
Giờ đây, dù bạn đang ở trang chủ hay trang tin tức, icon giỏ hàng vẫn luôn hiển thị con số chính xác.
Câu 3: Trang Giỏ Hàng Và Logic Tính Tổng Tiền
Tại trang /giohang, chúng ta sẽ liệt kê danh sách các món đồ đã chọn. Tại đây, người dùng có thể:
Thay đổi số lượng: Sử dụng dispatch(updateCartItemQuantity(...)).
Xóa sản phẩm: Sử dụng dispatch(removeFromCart(id)).
Xem tổng tiền: Sử dụng useMemo để tính toán lại tổng số tiền mỗi khi giỏ hàng thay đổi, giúp tối ưu hiệu năng render.
const total = useMemo(() =>
cartItems.reduce((total, item) => total + item.price * item.quantity, 0),
[cartItems]
);
Tại sao chọn Redux Toolkit thay vì State thông thường?
Global State: Dữ liệu tồn tại xuyên suốt quá trình chuyển trang của Next.js.
Predictable (Dễ đoán): Với action và payload, bạn luôn biết chính xác tại sao trạng thái ứng dụng thay đổi.
Dễ bảo trì: Logic thêm/xóa/sửa được tập trung tại một file cartslice.js duy nhất thay vì rải rác ở nhiều Component.
Tổng kết chuỗi bài Lab FE2
Trải qua 4 bài Lab, chúng ta đã xây dựng hoàn thiện một bộ khung Fullstack:
Backend: Node.js, Express, MongoDB.
Frontend: Next.js, Bootstrap.
Tương tác: Fetch API (Server & Client), useSWR.
Quản lý nâng cao: Redux Toolkit.
Hy vọng chuỗi bài viết này giúp các bạn có cái nhìn tổng quan và thực hành hiệu quả trên hành trình trở thành Web Developer. Chúc các bạn bảo vệ Lab thành công rực rỡ và đạt điểm 10 tuyệt đối!
All Rights Reserved