Reactreact-router

Cách sử dụng React Router trên project React

By Thái Nguyễn
Picture of the author
Published on
image alt attribute

React Router hay còn gọi là React Router Dom là một thư viện về Routing phổ biến và mạnh mẽ dành cho các ứng dụng React. React Router dễ dàng khi xử lý các task liên quan đến URL params, điều hướng, loading data, dynamic layout ...

Trong bài viết này, mình sẽ hướng dẫn cách dùng React Router một cách cơ bản và đầy đủ để có thể xây dựng lên 1 bộ routers hoàn chỉnh cho 1 web application.



Setup Project

Chạy câu lệnh dưới đây để tạo project react sử dụng typescript:

> npx create-react-app ReactRouterAuthDemo --template typescript
> cd ReactRouterAuthDemo

Install thư viện React Router V6

> npm install react-router-dom

Sau khi thư viện React Router được install, chúng ta sẽ cần sửa file: src/index.tsx

Import BrowserRouter từ react-router-dom và sau đó bọc <App /> component với <BrowserRouter />, như sau:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

Bây giờ có thể sử dụng các components và hooks của React Router từ bất kỳ đâu trong application.


Basic routing

React Router cung cấp 2 component RoutesRoute sử dụng để render các components dựa vào location hiện tại.

location là keyword đươc nhắc đến khá nhiều trong React Router, nó là một interface của thư viện history. Location là một entry trong history stack, thường tương tự như một "page" hoặc "screen" trong ứng dụng của bạn. Khi người dùng click vào link và điều hướng xung quanh các pages của ứng dụng, location hiện tại sẽ thay đổi.

import "./App.css";
import { Route, Routes } from "react-router-dom";
import HomePage from "./pages/Home";
import LoginPage from "./pages/Login";

function App() {
  return (
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route path="/login" element={<LoginPage />} />
    </Routes>
  );
}

export default App;
Cách sử dụng <Route >

<Route /> sẽ mapping giữa các paths trên application và các components React. Ví dụ: để hiển thị component LoginPage khi ai đó điều hướng đến /login, chúng ta chỉ cần tạo <Route />, như sau:

<Route path="/login" element={<LoginPage />} />

<Route /> component hoạt động như một câu lệnh if; nếu location thay đổi và matches với path thì sẽ hiển thị element tương ứng.

Cách sử dụng <Routes />

<Routes /> component sẽ thay thế cho <Switch /> component từ React Router v5.

Để sử dụng <Routes />, chúng ta sẽ tạo Login.tsx và Home.tsx files trong thư mục pages với nội dung như sau:

// Home.tsx
const HomePage = () => {
  return <div>HomePage</div>;
};

export default HomePage;
// Login.tsx
const LoginPage = () => {
  return <div>LoginPage</div>;
};

export default LoginPage;

Tiếp theo, chúng ta sẽ start app để test:

> npm run start

Trên browser, chúng ta sẽ thấy HomePage component. Nếu chúng ta nhập path /login, chúng ta sẽ thấy LoginPage component được render trên màn hình.


Sử dụng useRoutes() thay thế cho <Routes /><Route />

Ngoài ra, chúng ta có thể sử dụng plain JavaScript object để định nghĩa các routes cho Application sử dụng useRoutes hook. useRoutes hook là một cách định nghĩa khác và hoạt động giống với <Routes /><Route /> components.

import "./App.css";
import { Route, Routes } from "react-router-dom";
import HomePage from "./pages/Home";
import LoginPage from "./pages/Login";

export default function App() {
  const routes = useRoutes([
    {
      path: "/",
      element: <HomePage />
    },
    {
      path: "/login",
      element: <LoginPage />
    }
  ]);
  return routes;
}

Lazy loading routes

Nếu chúng ta import các components như ví dụ ở trên, khi truy cập application tất cả các component sẽ được render dù chúng ta không truy cập path match với component đó. Hãy cùng theo dõi ảnh dưới đây:

Screenshot 2023-11-02 at 15.37.49

Có thể thấy dù chúng ta không truy cập /login path nhưng component LoginPage component vẫn được render trong file bundle.js. Tại thuộc tính children, có thể thấy đầy đủ nội dung của LoginPage Component.

Nếu Web Application có hàng chục hàng trăm routers khác nhau và chứa nhiều logic phức tạp thì thời gian load web sẽ rất chậm. Để tối ưu performance thì chúng ta sẽ chỉnh sửa ví dụ như sau:

import React from "react";

import "./App.css";
import { Route, Routes } from "react-router-dom";
const HomePage = React.lazy(() => import("./pages/Home"));
const LoginPage = React.lazy(() => import("./pages/Login"));

function App() {
  return (
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route path="/login" element={<LoginPage />} />
    </Routes>
  );
}

export default App;

Sử dụng lazy() của React giúp chúng ta sẽ chỉ load component chỉ khi location match với path của router, không load component không liên quan giúp tăng đáng kể performance.


URL Parameters

Giống như các tham số function cho phép bạn khai báo và giữ chỗ khi bạn define 1 function, URL Parameters cho phép bạn khai báo và giữ chỗ cho các phần của URL.

Ví dụ: Khi bạn truy cập một chủ đề trên Wikipedia, bạn sẽ nhận thấy rằng mẫu URL luôn giống nhau, wikipedia.com/wiki/topicId.

Cách khai báo 1 param topicId với React Router:

<Route path="/wiki/:topicId" element={<Article />} />

Lấy param topicId như sau:

import { useParams } from 'react-router-dom'

function Article () {
  const { topicId } = useParams()

  return (
    ...
  )
}

Điều hướng

Để điều hướng web application sang các page khác nhau chúng ta sử dụng thẻ Link của React Router như sau:

import { Link } from "react-router-dom";

function Article () {
   ...
    return (
        <nav>
            <Link to="/">Home</Link>
            <Link to="/about">About</Link>
            <Link
                to={{
                    pathname: "/settings",
                    search: "?sort=date",
                    state: { fromHome: true },
                }}
            >
                Settings
            </Link>
        </nav>
    )
}

Nếu bạn muốn điều hướng trong các function, logic code, event, thì hãy sử dụng useNavigate hook của React Router cung cấp:

import { useNavigate } from 'react-router-dom

function Register () {
  const navigate = useNavigate()

  return (
    <div>
      <h1>Register</h1>
      <Form afterSubmit={() => navigate('/dashboard')} />
    </div>
  )
}

Tạo Not Found Page

Để điều hướng web đến page Not Found nếu người dùng nhập path không tồn tại thì chúng ta tạo component NotFoundPage sau đó sửa file App.tsx:

import React from "react";

import "./App.css";
import { Route, Routes } from "react-router-dom";
const HomePage = React.lazy(() => import("./pages/Home"));
const LoginPage = React.lazy(() => import("./pages/Login"));
const NotFoundPage = React.lazy(() => import("./pages/NotFound"));

function App() {
  return (
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route path="/login" element={<LoginPage />} />
      <Route path="*" element={<NotFoundPage />} />
    </Routes>
  );
}

export default App;

Conclusion

Trên đây là những kiến thức cơ bản nhất về React Router, trong phần tiếp theo mình sẽ viết về cách sử dụng Multiple Layout, Phân quyền và xác thực sử dụng Protected Routes trong React Router - một tính năng rất quan trọng và thiết yếu trên mọi web app.

=> Link bài tiếp theo:

https://www.nguyenvanthai.com/blog/react/multiple-layout-su-dung-react-router-trong-reactjs https://www.nguyenvanthai.com/blog/react/protected-routes-trong-react-js-su-dung-react-router-dom-v6

Hãy comment nếu bạn có điều gì thắc mắc hoặc muốn trao đổi thêm về bài viết này nhé 🥰