วันนี้จะมาบันทึกการลองใช้งาน React Router v6 ดูครับ ซึ่งจริงๆแล้วมันยังเป็น Alpha อยู่และอาจจะมี breaking change หรือ API บางอย่างที่มันเปลี่ยนก็ได้ ฉะนั้นบทความนี้ เป็นเพียงบทความที่อิงจาก alpha เท่านั้นนะครับ หากใครมาอ่านบทความ ในขณะที่ตัว React Router มันออกเวอร์ชั่นเต็มแล้ว ก็ต้องเช็คความถูกต้องกันดูอีกทีครับ

สืบเนื่องจากผมได้ลอง React Router ตอน v4 และลองเปลี่ยนไปใช้ reach/router อยู่ช่วงนึง และพบว่ามันค่อนข้างง่ายแฮะ และแอบสงสัยว่าทำไมคนทำ React Router เค้าต้องไปทำอันใหม่ด้วย สุดท้ายก็กลับมารวมทีมกัน ทำ React Router ครับ ตัว reach/router ก็ยังใช้ได้ และพวก syntax ของ reach/router บางส่วนก็มาอยู่ใน React Router v6 เหมือนกัน (เรื่องราวของทีมที่ทำ เหมือนว่าทะเลาะกัน อาจจะด้วยความเห็นไม่ตรงกันหรืออะไรไม่รู้ ผมไม่แน่ใจนะครับ)

React Router v6 Alpha!

ตัว v6 นั้นลด Bundle size จาก v5 ลงมามากกว่า 70% เลยครับ

React Router v6

จาก https://twitter.com/ryanflorence/status/1229134773282455554

ซึ่งก่อนใช้ v6 เราต้องแน่ใจก่อนว่า

  • ต้องใช้ React v16.8 ขึ้นไป เพราะ React Router v6 ใช้ Hook ครับ
  • ต้อง install โดยใช้ @next ครับ หรือ
npm install react-router@6 react-router-dom@6

อ่านค่า URL Params

เราสามารถใช้ hook useParams() เพื่ออ่านค่าได้ง่ายๆ เลย โดยที่เรากำหนด dynamic ไว้ที่ <Route path=""> ครับ ตัวอย่างเช่น

import { Routes, Route, useParams } from 'react-router-dom';

function Invoice() {
  let { invoiceId } = useParams();
  return <h1>Invoice {invoiceId}</h1>;
}

function App() {
  return (
    <Routes>
      <Route path="invoices/:invoiceId" element={<Invoice />} />
    </Routes>
  );
}

Route Path

เปลี่ยนจาก <Route render> เป็นใช้ <Route element> แทน

และตัว path ไม่รองรับแบบ Regex แล้วครับ ตอนนี้ Path รองรับแค่แบบปกติ dynamic แล้วก็ wildcard แบบ (/*)

ใช้ <Routes> มาครอบ <Route> หรือทำ multiple Route ได้เช่นกัน

function App() {
  return (
    <Routes>
      <Route path="invoices/:invoiceId" element={<Invoice />} />
      <Route path="invoices/sent" element={<SentInvoices />} />
    </Routes>
  );
}

Nested Route ซ้อนกันก็ทำได้ โดยใช้ <Outlet> ครับ

import { Routes, Route, Outlet } from 'react-router-dom';

function Invoices() {
  return (
    <div>
      <h1>Invoices</h1>

      {/*
        This element renders the element for the child route, which in
        this case will be either <SentInvoices> or <IndividualInvoice>
      */}
      <Outlet />
    </div>
  );
}

function IndividualInvoice() {
  let { invoiceId } = useParams();
  return <h1>Invoice {invoiceId}</h1>;
}

function SentInvoices() {
  return <h1>Sent Invoices</h1>;
}

function App() {
  return (
    <Routes>
      <Route path="invoices" element={<Invoices />}>
        <Route path=":invoiceId" element={<IndividualInvoice />} />
        <Route path="sent" element={<SentInvoices />} />
      </Route>
    </Routes>
  );
}

ข้อนี้แค่เปลี่ยนจาก <Link component> เป็น <Link as>

และ <Link to="/"> ไม่ต้อง start ด้วย slash แล้วครับ (เป็น relative path นะครับ ฉะนั้นจะใช้ / หรือไม่ใช้ ขึ้นอยู่กับจุดประสงค์ครับ)

Router config

เราสามารถกำหนด Router แบบ config style ได้ จริงๆน่าจะตั้ง v4-v5 ละครับ

[
  { paht: '/', element: Home },
  { path: '/about', element: About}
]

ซึ่งพอเป็น v6 เราใช้ Hook ชื่อ useRoutes ตัวเดียวจบเลย

const App = () => {
  const routes = useRoutes([
    { paht: '/', element: Home },
    { path: '/about', element: About}
  ]);

  return routes;
}

404 Route

อยากกำหนด 404 Route ก็ทำได้งา่ยๆ ด้วย wildcard

<Route path="*" element={<NoMatch />} />

ใน v6 เราใช้ useNavigation hook เพื่อ push history หรือ change url ได้เลยครับ เหมือนกับ history.push() ซึ่งมันเปลี่ยนชื่อจาก useHistory() นั่นเอง ตัวอย่าง

import { useNavigate } from 'react-router-dom';

function App() {
  let navigate = useNavigate();
  function handleClick() {
    navigate('/home')
  }
  return (
    <div>
      <button onClick={handleClick}>go home</button>
    </div>
  );
}

หรือแบบใช้ Component ก็ได้ ตอน v5 ใช้ชื่อ <Redirect> เช่น

import { Navigate } from 'react-router-dom';

function App() {
  return <Navigate to="/home" replace state={state} />;
}

บทความนี้ผมก็สรุปๆ สั้นๆ ยกเรื่องที่น่าสนใจ เอาสิ่งที่ผมคิดว่าน่าจะได้ใช้ตอน v6 จากบทความ Refenreces ที่ผมแนบไว้ด้านล่างนะครับ หากใครอยากอ่านรายละเอียดเต็มๆ ก็ไปอ่านเพิ่มเติมได้ครับ

ขอบคุณครับ

❤️ Happy Coding

References