0
0
Lập trình
Admin Team
Admin Teamtechmely

Hướng Dẫn Sử Dụng Data APIs trong React Router v6.4

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

• 9 phút đọc

Hướng Dẫn Sử Dụng Data APIs trong React Router v6.4

Giới thiệu

Phiên bản React Router v6.4 đã giới thiệu Data APIs — một nâng cấp quan trọng cho phép chúng ta xử lý lấy dữ liệu, biến đổi (hành động), và xử lý lỗi trực tiếp trong định nghĩa các route. Trong hướng dẫn này, chúng ta sẽ xây dựng một ứng dụng demo nhỏ sử dụng Vite + React Router + JSON Server.

Tại sao chọn React Router v6.4?

React Router là một thư viện quan trọng trong phát triển ứng dụng React, giúp quản lý điều hướng và trạng thái của ứng dụng. Với bản cập nhật này, React Router không chỉ dừng lại ở việc điều hướng mà còn mở rộng tới việc quản lý dữ liệu và giao diện.

Nội dung

Giới thiệu về createBrowserRouter

createBrowserRouter là một hàm được giới thiệu trong React Router v6.4 như một phần của Data APIs mới. Nó:

  • Định nghĩa tất cả các route trong một đối tượng cấu hình duy nhất.
  • Hỗ trợ tải dữ liệu, xử lý lỗi và hành động.
  • Thay thế cấu hình cũ <BrowserRouter> + <Routes> + <Route>.
  • Phải kết hợp với <RouterProvider>.

Điều này có nghĩa là routing hiện đã vượt xa điều hướng — nó còn liên quan đến dữ liệu + phối hợp giao diện.

Cài đặt và cấu hình

Để bắt đầu, chúng ta sẽ tạo một dự án mới bằng Vite:

bash Copy
# Tạo dự án Vite
npm create vite@latest react-data-api-demo
cd react-data-api-demo
npm install

# Cài đặt các thư viện cần thiết
npm install react-router-dom

# Cài đặt JSON Server cho backend giả lập
npm install -g json-server

Thiết lập JSON Server

Tạo một tệp có tên db.json trong thư mục gốc của dự án:

json Copy
{
    "users": [
        {
            "id": "1",
            "name": "Leanne Graham",
            "email": "Sincere@april.biz"
        },
        {
            "id": "2",
            "name": "Ervin Howell",
            "email": "Shanna@melissa.tv"
        }
    ]
}

Chạy JSON Server:

bash Copy
json-server --watch db.json --port 5000

Cấu trúc dự án

Dự án của chúng ta sẽ có cấu trúc như sau:

Copy
src/
 ├── App.jsx
 ├── main.jsx
 ├── router.js
 ├── pages/
 │    ├── Users.jsx
 │    ├── NewUserForm.jsx
 │    └── ErrorPage.jsx
 └── db.json

Mã nguồn

main.jsx

javascript Copy
import { createRoot } from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import router from "./router";

createRoot(document.getElementById("root")).render(
    <RouterProvider router={router} />
);

router.js

javascript Copy
import { createBrowserRouter } from "react-router-dom";
import App from "./App";
import ErrorPage from "./pages/ErrorPage";
import Users, { usersLoader } from "./pages/Users";
import NewUserForm, { addUserAction } from "./pages/NewUserForm";

const router = createBrowserRouter([
    {
        path: "/",
        element: <App />,
        errorElement: <ErrorPage />,
        children: [
            {
                path: "users",
                element: <Users />,
                loader: usersLoader, // GET -> fetch users
            },
            {
                path: "users/new",
                element: <NewUserForm />,
                action: addUserAction, // POST -> add user
            },
        ],
    },
]);

export default router;

App.jsx

javascript Copy
import { NavLink, Outlet } from "react-router-dom";

const App = () => {
    return (
        <div style={{ padding: "20px" }}>
            <h1>🚀 Ví dụ về Loader + Action của React Router</h1>

            {/* Điều hướng */}
            <nav style={{ marginBottom: "20px" }}>
                <NavLink to="/" style={{ marginRight: "10px" }}>
                    Trang Chủ
                </NavLink>
                <NavLink to="/users" style={{ marginRight: "10px" }}>
                    Người Dùng
                </NavLink>
                <NavLink to="/users/new">Thêm Người Dùng</NavLink>
            </nav>

            {/* Nơi đây sẽ hiển thị các route con */}
            <Outlet />
        </div>
    );
};

export default App;

pages/Users.jsx

javascript Copy
import { useLoaderData, Link } from "react-router-dom";

export const usersLoader = async () => {
    const response = await fetch("http://localhost:5000/users");

    if (!response.ok) {
        throw new Response("Lỗi khi tải người dùng", { status: response.status });
    }

    return response.json();
};

export default function Users() {
    const users = useLoaderData();

    return (
        <div>
            <h2>Danh Sách Người Dùng</h2>
            <Link to="/users/new">➕ Thêm Người Dùng Mới</Link>
            <ul>
                {users.map((user) => (
                    <li key={user.id}>
                        {user.name} - {user.email}
                    </li>
                ))}
            </ul>
        </div>
    );
}

pages/NewUserForm.jsx

javascript Copy
import { Form, redirect } from "react-router-dom";

export const addUserAction = async ({ request }) => {
    const formData = await request.formData();
    const newUser = {
        name: formData.get("name"),
        email: formData.get("email"),
    };

    // Giả lập yêu cầu POST
    const response = await fetch("http://localhost:5000/users", {
        method: "POST",
        body: JSON.stringify(newUser),
        headers: { "Content-Type": "application/json" },
    });

    if (!response.ok) {
        throw new Response("Lỗi khi thêm người dùng", { status: response.status });
    }

    // Sau khi thành công -> chuyển hướng về danh sách người dùng
    return redirect("/users");
};

const NewUserForm = () => {
    return (
        <div>
            <h2>Thêm Người Dùng Mới</h2>
            <Form method="post">
                <input
                    type="text"
                    name="name"
                    id="name"
                    placeholder="Tên"
                    required
                />
                <input
                    type="email"
                    name="email"
                    id="email"
                    placeholder="Email"
                    required
                />
                <button type="submit">Lưu</button>
            </Form>
        </div>
    );
};

export default NewUserForm;

pages/ErrorPage.jsx

javascript Copy
import { useRouteError } from "react-router-dom";

const ErrorPage = () => {
    const error = useRouteError();

    return (
        <div style={{ padding: "20px", color: "red" }}>
            <h2>⚠ Oops! Đã có lỗi xảy ra</h2>
            <p>{error.statusText || error.message}</p>
        </div>
    );
};

export default ErrorPage;

Cách hoạt động

  1. Truy cập /usersLoader chạy → Lấy danh sách người dùng → Hiển thị danh sách.
  2. Nhấn Thêm Người Dùng Mới → Điều hướng đến /users/new.
  3. Điền thông tin → Action chạy → Gửi yêu cầu POST.
  4. Khi thành công → Chuyển hướng về /users với dữ liệu cập nhật.
  5. Khi có lỗi → ErrorPage hiển thị lỗi.

Chạy ứng dụng

Để chạy ứng dụng, chúng ta cần khởi động cả JSON Server và Vite:

bash Copy
# Khởi động JSON Server
json-server --watch db.json --port 5000

# Khởi động Vite
npm run dev

Bây giờ mở trình duyệt và truy cập http://localhost:5173/users 🎉

Kết luận

Với Data APIs trong React Router v6.4, việc lấy dữ liệu và gửi biểu mẫu trở nên có cấu trúc và tuyên bố hơn. Kết hợp với Vite và JSON Server, bạn có thể dễ dàng thử nghiệm và xây dựng các demo nhỏ.

👉 Nếu bạn đang học React, hãy thử thiết lập này và khám phá cách mà loaders, actions và boundaries xử lý lỗi giúp đơn giản hóa việc quản lý dữ liệu!

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