React Router Cheatsheet và mọi thứ bạn cần biết (Phần 2)

2494

Tác giả: Reed Barger

Thành phần liên kết

Giả sử với NavBar, chúng tôi muốn tạo một số liên kết để có thể di chuyển xung quanh ứng dụng của mình dễ dàng hơn thay vì phải thay đổi URL theo cách thủ công trong trình duyệt.

Chúng ta có thể làm như vậy với một thành phần đặc biệt khác từ React Router DOM là Link component. Nó chấp nhận prop to, chỉ định nơi muốn liên kết điều hướng người dùng đến. Trong trường hợp này có thể có một liên kết về:

import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";

export default function App() {
  return (
    <Router>
      <Navbar />
      <Switch>
        <Route path="/" component={Home} />
        <Route path="/about" component={About} />
      </Switch>
    </Router>
  );
}

function Navbar() {
  return (
    <nav>
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
    </nav>
  )
}

Thành phần liên kết cho phép cung cấp một số inline styles giống như bất kỳ thành phần React tiêu chuẩn nào. Nó cũng cung cấp một prop component hữu ích, vì vậy chúng tôi có thể đặt liên kết của mình làm thành phần tùy chỉnh riêng để tạo kiểu dễ dàng hơn.

Tìm việc làm React lương cao up to 2000USD

Ngoài ra, React Router DOM cũng cung cấp NavLink Component rất hữu ích trong trường hợp muốn áp dụng một số kiểu đặc biệt.

Nếu bạn đang ở trên đường dẫn mà liên kết trỏ đến, điều này cho phép tạo một số kiểu liên kết hoạt động để cho người dùng biết, bằng cách xem liên kết đang ở trang nào.

Ví dụ, nếu người dùng đang ở trên trang chủ, chúng tôi có thể cho họ biết càng nhiều bằng cách sử dụng phần mềm activeStyle hỗ trợ để làm cho liên kết được in đậm và có màu đỏ khi họ ở trên trang chủ:

import {
  BrowserRouter as Router,
  Switch,
  Route,
  NavLink
} from "react-router-dom";

export default function App() {
  return (
    <Router>
      <Navbar />
      <Switch>
        <Route path="/" component={Home} />
        <Route path="/about" component={About} />
      </Switch>
    </Router>
  );
}

function Navbar() {
  return (
    <nav>
      <NavLink
        activeStyle={{
          fontWeight: "bold",
          color: "red"
        }}
        to="/"
      >
        Home
      </NavLink>
      <NavLink activeClassName="active" to="/about">
        About
      </NavLink>
    </nav>
  );
}

Ngoài ra còn có prop activeClassName có thể được thiết lập nếu bạn không muốn bao gồm các inline styles hoặc muốn nhiều kiểu có thể tái sử dụng hơn để thực hiện cùng một chức năng activeStyle.

  Bỏ túi cheatsheet dành cho Python newbie
  React Props Cheatsheet: 10 Patterns mà bạn nên biết (Phần 1)

Thành phần chuyển hướng

Một thành phần rất hữu ích khác mà React Router DOM cung cấp là thành phần chuyển hướng. Điều này có vẻ lạ khi có một thành phần thực hiện chức năng chuyển hướng người dùng khi nó được hiển thị, nhưng lại rất hữu ích.

Bất cứ khi nào bạn sử dụng một cái gì đó như một private route và có điều kiện trong đó người dùng không được xác thực, bạn có thể chuyển hướng họ trở lại trang đăng nhập.

Dưới đây là một ví dụ về việc triển khai các thành phần về private route đảm bảo rằng người dùng được xác thực trước khi nó hiển thị cho họ một route cụ thể đã được khai báo với thành phần này.

Ngược lại, nếu chúng không được xác thực, chúng sẽ được chuyển hướng đến một public route (có thể là một route để đăng nhập) khi thành phần chuyển hướng được hiển thị:

import {
  BrowserRouter as Router,
  Switch,
  Route,
  Redirect
} from "react-router-dom";

export default function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <PrivateRoute path="/hidden" component={Hidden} />
      </Switch>
    </Router>
  );
}

function PrivateRoute({ component: Component, ...rest }) {
  // useAuth is some custom hook to get the current user's auth state
  const isAuth = useAuth();

  return (
    <Route
      {...rest}
      render={(props) =>
        isAuth ? <Component {...props} /> : <Redirect to="/" />
      }
    />
  );
}

function Home() {
  return <>home</>;
}

function Hidden() {
  return <>hidden</>;
}

useHistory Hook

Trên tất cả các thành phần đầy chất lượng này, có một số hook rất hữu ích mà React Router DOM cung cấp thêm cho chúng ta.

Chúng chủ yếu hữu ích bằng cách cung cấp thông tin bổ sung mà bạn có thể sử dụng trong các thành phần của mình. Chúng có thể được gọi là các React hook bình thường mà chúng ta có thể sử dụng các giá trị của chúng một cách chính xác theo ý muốn.

  Bỏ túi Cheatsheet React cho năm 2023 (kèm ví dụ thực tế)

Có lẽ một trong những hook hữu dụng nhất chính là useHistory hook. Có thể sử dụng nó ở đầu bất kỳ thành phần nào được khai báo trong thành phần bộ định tuyến của chúng tôi và lấy lại các dữ liệu history, bao gồm thông tin như vị trí được liên kết với thành phần chẳng hạn.

Điều này cho chúng ta biết tất cả về vị trí hiện tại của người dùng, chẳng hạn như tên đường dẫn mà họ đang truy cập, cũng như bất kỳ tham số truy vấn nào có thể được thêm vào URL của chúng tôi. Tất cả dữ liệu vị trí đều có thể truy cập được từ history.location:

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


function About() {
  const history = useHistory();
    
  console.log(history.location.pathname); // '/about'

  return (
    <>
     <h1>The about page is on: {history.location.pathname}</h1>
    </>
  );
}

Ngoài ra, các thông tin lịch sử trực tiếp bao gồm các phương pháp hữu ích cho phép hướng người dùng theo chương trình đến các trang khác nhau trong ứng dụng của bạn.

Điều này rất hữu ích, ví dụ, để chuyển hướng người dùng sau khi đăng nhập hoặc trong bất kỳ tình huống nào mà cần phải đưa người dùng từ trang này sang trang khác.

Chúng tôi có thể đẩy người dùng từ trang này sang trang khác bằng cách sử dụng history.push. Khi sử dụng phương pháp đẩy, bạn chỉ cần cung cấp đường dẫn mà chúng tôi muốn đưa người dùng của mình đến bằng cách sử dụng phương pháp này. Nó thêm trang mới này vào stack về lịch sử:

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


function About() {
  const history = useHistory();
    
  console.log(history.location.pathname); // '/about'

  return (
    <>
     <h1>The about page is on: {history.location.pathname}</h1>
     <button onClick={() => history.push('/')}>Go to home page</button>
    </>
  );
}

Cũng có thể chuyển hướng người dùng bằng history.replace, giá trị này cũng chấp nhận giá trị đường dẫn, nhưng xóa mọi thứ trong lịch sử, sau khi điều hướng được thực hiện. Điều này rất hữu ích cho những trường hợp không cần quay lại lịch sử, chẳng hạn như sau khi người dùng đã đăng xuất.

useLocation Hook

Các useLocation hook bao gồm tất cả các thông tin tương tự mà useHistory hook làm.

Điều quan trọng cần lưu ý là nếu bạn cần cả dữ liệu vị trí và sử dụng lịch sử để điều hướng người dùng của mình theo chương trình, hãy đảm bảo sử dụng History. Tuy nhiên, nếu bạn chỉ muốn dữ liệu vị trí, tất cả những gì bạn cần làm là sử dụng useLocation hoặc lấy lại tất cả dữ liệu vị trí trên một đối tượng giống với dữ liệu được cung cấp trên history. location:

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


function About() {
  const location = useLocation();
    
  console.log(location.pathname); // '/about'

  return (
    <>
     <h1>The about page is on: {location.pathname}</h1>
    </>
  );
}

useParams Hook + Dynamic Routes

Một điều mà chúng tôi không đề cập đến khi nói đến các routes là chúng tôi có thể tạo ra các dynamic routes một cách tự nhiên. Điều này có nghĩa là các tuyến không cố định và được xác định, nhưng có thể là bất kỳ số ký tự nào.

Các dynamic routes rất hữu ích trong các tình huống mà chúng tôi có, chẳng hạn như một bài đăng trên blog với một slug duy nhất. Làm cách nào để đảm bảo rằng chúng tôi hiển thị dữ liệu và các thành phần một cách thích hợp, vì slug bài đăng trên blog của chúng tôi có thể hoàn toàn khác?

Để khai báo một tham số route trên một route nhất định, nó phải được đặt trước bằng dấu hai chấm :. Nếu muốn tạo một dynamic route, “/ blog /: postSlug”, cho một thành phần bài đăng trên blog, nó có thể giống như sau:

import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

export default function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/blog/:postSlug" component={BlogPost} />
      </Switch>
    </Router>
  );
}

function Home() {
  return <>home</>;
}

function BlogPost() {
  return <>blog post</>;
}

Nhưng trong thành phần BlogPost, làm cách nào để nhận được dữ liệu slug của bài đăng đó? Chúng ta có thể truy cập bất kỳ thông số tuyến nào của một tuyến đã khai báo với thành phần liên kết của nó bằng cách sử dụng useParams hook.

useParams sẽ trả về một đối tượng sẽ chứa các thuộc tính phù hợp với các tham số tuyến của chúng ta (trong trường hợp này là postSlug). Chúng ta có thể sử dụng cấu trúc đối tượng để truy cập ngay lập tức và khai báo dưới dạng một biến với tên postSlug:

import React from "react";
import { BrowserRouter as Router, Switch, Route, useParams } from "react-router-dom";

export default function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/blog/:postSlug" component={BlogPost} />
      </Switch>
    </Router>
  );
}

function Home() {
  return <>home</>;
}

function BlogPost() {
  const [post, setPost] = React.useState(null);
  const { postSlug } = useParams();

  React.useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${postSlug}`)
      .then((res) => res.json())
      .then((data) => setPost(data));
  }, [postSlug]);

  if (!post) return null;

  return (
    <>
      <h1>{post.title}</h1>
      <p>{post.description}</p>
    </>
  );
}

useRouteMatch Hook

Nếu muốn biết liệu thành phần đã cho có nằm trên một trang nhất định hay không, chúng ta có thể sử dụng useRouteMatch hook.

Ví dụ: trong bài đăng trên blog, để xem liệu trang chúng tôi đang truy cập có khớp với tuyến đường “/ blog /: postSlug” hay không, chúng tôi có thể lấy lại giá trị boolean sẽ cho chúng tôi biết liệu tuyến đường mà chúng tôi đang truy cập có khớp với mà chúng tôi đã chỉ định:

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

function BlogPost() {
  const isBlogPostRoute = useRouteMatch("/blog/:postSlug");
 
  // display, hide content, or do something else
}

Phỏng dịch theo bài viết gốc tại freecodecamp.org

Có thể bạn quan tâm:

Xem thêm tuyển dụng it hấp dẫn trên TopDev