0
0
Lập trình
Harry Tran
Harry Tran106580903228332612117

Hướng dẫn sử dụng Cursor Pagination với Redux Toolkit

Đăng vào 2 tháng trước

• 6 phút đọc

Giới thiệu

Trong bài viết này, chúng ta sẽ tìm hiểu cách sử dụng cursor pagination trong ứng dụng React với Redux Toolkit. Cursor pagination là một kỹ thuật hữu ích để quản lý dữ liệu trong các ứng dụng có lượng thông tin lớn, giúp tối ưu hóa việc tải và hiển thị dữ liệu. Chúng ta sẽ cùng nhau xây dựng một ví dụ cụ thể để áp dụng kỹ thuật này.

Mục tiêu của bài viết

  • Quản lý dữ liệu phân trang hiệu quả với cursor.
  • Sử dụng Redux Toolkit để quản lý trạng thái ứng dụng.
  • Tạo một giao diện người dùng đơn giản để hiển thị dữ liệu.

Nội dung bài viết

1. Slice của Redux

Đầu tiên, chúng ta sẽ tạo một slice cho pagination trong Redux. Dưới đây là mã nguồn cho slice này:

javascript Copy
// store/paginationSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

// Thunk để lấy kết quả từ API với cursor
export const fetchPage = createAsyncThunk(
  "pagination/fetchPage",
  async ({ cursor, sort }, thunkAPI) => {
    const response = await fetch(
      `/api/items?cursor=${cursor || ""}&sort=${sort}`
    );
    const data = await response.json();
    return data; 
    // Giả sử data = { items: [...], nextCursor: "abc", previousCursor: "xyz" }
  }
);

const paginationSlice = createSlice({
  name: "pagination",
  initialState: {
    items: [],
    nextCursor: null,
    previousCursor: null,
    sort: "docdate:asc",
    loading: false,
    error: null,
  },
  reducers: {
    changeSorting: (state, action) => {
      state.sort = action.payload;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchPage.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchPage.fulfilled, (state, action) => {
        state.loading = false;
        state.items = action.payload.items;
        state.nextCursor = action.payload.nextCursor;
        state.previousCursor = action.payload.previousCursor;
      })
      .addCase(fetchPage.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

export const { changeSorting } = paginationSlice.actions;
export default paginationSlice.reducer;

Chú thích mã nguồn

  • fetchPage: Đây là một thunk dùng để gọi API và lấy dữ liệu phân trang.
  • paginationSlice: Slice này quản lý trạng thái của các item, cursor và trạng thái loading/error.

2. Cấu hình Store

Tiếp theo, chúng ta sẽ cấu hình Redux store để sử dụng slice vừa tạo:

javascript Copy
// store/index.js
import { configureStore } from "@reduxjs/toolkit";
import paginationReducer from "./paginationSlice";

export const store = configureStore({
  reducer: {
    pagination: paginationReducer,
  },
});

Chú thích mã nguồn

  • configureStore: Hàm này cấu hình store với reducer cho pagination.

3. Cung cấp Store trong ứng dụng

Chúng ta cần cung cấp store cho ứng dụng React bằng cách sử dụng Provider:

javascript Copy
// main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import { store } from "./store";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")).render(
  <Provider store={store}>
    <App />
  </Provider>
);

Chú thích mã nguồn

  • Provider: Component này cung cấp Redux store cho toàn bộ ứng dụng.

4. Tạo thành phần với Paginattion và Sắp xếp

Giờ đây, chúng ta sẽ tạo một thành phần để hiển thị dữ liệu, cho phép người dùng phân trang và sắp xếp:

javascript Copy
// App.jsx
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchPage, changeSorting } from "./store/paginationSlice";

export default function App() {
  const { items, nextCursor, previousCursor, sort, loading, error } = useSelector(
    (state) => state.pagination
  );
  const dispatch = useDispatch();

  // Tải dữ liệu lần đầu tiên
  useEffect(() => {
    dispatch(fetchPage({ cursor: null, sort }));
  }, [dispatch, sort]);

  const handleNext = () => {
    if (nextCursor) dispatch(fetchPage({ cursor: nextCursor, sort }));
  };

  const handlePrevious = () => {
    if (previousCursor) dispatch(fetchPage({ cursor: previousCursor, sort }));
  };

  const handleSortChange = (e) => {
    dispatch(changeSorting(e.target.value));
    dispatch(fetchPage({ cursor: null, sort: e.target.value }));
  };

  return (
    <div>
      <h1>Danh sách kết quả</h1>

      {loading && <p>Đang tải...</p>}
      {error && <p>Lỗi: {error}</p>}

      <select value={sort} onChange={handleSortChange}>
        <option value="docdate:asc">Ngày ↑</option>
        <option value="docdate:desc">Ngày ↓</option>
        <option value="slug:asc">Slug ↑</option>
        <option value="slug:desc">Slug ↓</option>
        <option value="score:asc">Điểm số ↑</option>
        <option value="score:desc">Điểm số ↓</option>
      </select>

      <ul>
        {items.map((item) => (
          <li key={item.id}>{item.title} — {item.date}</li>
        ))}
      </ul>

      <div>
        <button disabled={!previousCursor} onClick={handlePrevious}>
          ← Trở lại
        </button>
        <button disabled={!nextCursor} onClick={handleNext}>
          Tiếp theo →
        </button>
      </div>
    </div>
  );
}

Chú thích mã nguồn

  • Thành phần này sẽ hiển thị danh sách các item, trạng thái loading và cho phép người dùng điều chỉnh sắp xếp.

5. Quy trình hoàn chỉnh (pseudocode)

  1. Người dùng mở trang → useEffect gọi fetchPage({cursor: null, sort}).
  2. Redux chuyển trạng thái từ pending sang fulfilled và cập nhật items, nextCursor, previousCursor.
  3. Người dùng nhấn vào Tiếp theo → gọi fetchPage({cursor: nextCursor, sort}).
  4. API trả về trang tiếp theo → Redux cập nhật items và các cursor.
  5. Người dùng thay đổi sắp xếp → gọi changeSorting và tải lại trang đầu tiên.

Thực hành tốt nhất

  • Luôn kiểm tra trạng thái loading trước khi hiển thị dữ liệu.
  • Xử lý lỗi một cách thân thiện với người dùng.

Những cạm bẫy thường gặp

  • Không xử lý trường hợp không có dữ liệu trả về từ API.
  • Quên cập nhật các cursor khi dữ liệu mới được tải.

Mẹo hiệu suất

  • Giảm thiểu số lần gọi API bằng cách cache kết quả khi có thể.
  • Sử dụng lazy loading cho các phần tử không cần thiết hiển thị ngay lập tức.

Câu hỏi thường gặp (FAQ)

H1: Cursor pagination là gì?
Cursor pagination là một kỹ thuật phân trang giúp tải dữ liệu theo từng phần nhỏ hơn, sử dụng các cursor để xác định vị trí của dữ liệu.
H2: Tại sao nên sử dụng Redux Toolkit?
Redux Toolkit giúp đơn giản hóa việc quản lý trạng thái trong ứng dụng React, giảm thiểu boilerplate code và cải thiện khả năng bảo trì.

Kết luận

Trong bài viết này, chúng ta đã tìm hiểu cách sử dụng cursor pagination với Redux Toolkit trong ứng dụng React. Phương pháp này không chỉ giúp cải thiện hiệu suất của ứng dụng mà còn mang đến trải nghiệm người dùng tốt hơn. Hãy thử áp dụng vào dự án của bạn và theo dõi sự khác biệt!

Lời kêu gọi hành động

Nếu bạn thấy bài viết này hữu ích, hãy chia sẻ và theo dõi chúng tôi để nhận thêm nhiều kiến thức về phát triển ứng dụng!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào