วิธีการกำหนด Routes ของ React Router v6

เนื่องจากช่วงนี้ได้กลับมาทบทวน React Router เพื่อนำมาทำเป็นเนื้อหาในคอร์สสอน React เบื้องต้น หลังจากที่ไม่ได้ใช้ Client Routing มานานมากๆ แล้ว (ปัจจุบัน แอพ React ทั้งหมด ผมใช้ Next.js ทั้งสิ้น)
วันนี้ลองไปนั่งอ่าน Doc ทบทวน ก็เลยนำมาเขียนเป็นบทความบันทึกเอาไว้ ถึงวิธีการกำหนด Routes ใน React Router ว่ามันทำท่าไหนได้บ้าง และทำอะไรได้บ้าง
ซึ่งจริงๆ แล้ว จากหน้าเว็บ เราสามารถอ่าน Tutorial และลองทำตามได้เลยนะ ใช้เวลาประมาณ 1 ชั่วโมง
การเลือก Router
ใน React Router v6 (v6.4) มันจะมีเรื่องของ Data API เข้ามาเกี่ยวข้องด้วย ฉะนั้น ก็มีมีวิธีการสร้าง Route แบบที่ใช้ data API และแบบที่ไม่ใช้ Data API นั่นเอง
BrowserRouter
วิธีแรก ขอเป็นแบบปกติ ที่เคยใช้ใน v4 / v5 หรือพวก reach router หรือ client side router ที่คุ้นๆกัน นั่นก็คือ ใช้แบบ BrowserRouter component
สมมติต้องการสร้าง Page ทั้งหมด
/
- หน้า Home Page (มี Layout เหมือนกัน คือ navbar)/about
- หน้า About/dashboard
- หน้า Dashboard/*
- ไม่ match ซัก url เลยก็จะโชว์ component NoMatch
วิธีนี้ก็คือ ตัว <BrowserRouter>
จะเก็บข้อมูล location จาก url ไว้ใน ตัว built-in history stack ปกติของ Browser (เวลากด back)
import ReactDOM from 'react-dom/client'import { BrowserRouter } from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root')!).render(
{' '}
<React.StrictMode> <BrowserRouter> <App /> </BrowserRouter></React.StrictMode>)
ในส่วนที่เราต้องการกำหนด Routing ก็จะใช้ <Routes>
และ <Route>
ตัวอย่างเช่นไฟล์ App.tsx
(Source Code)
import { Routes, Route, Outlet, Link } from 'react-router-dom'
export default function App() { return ( <div> <h1>Basic Example</h1>
{/* Routes nest inside one another. Nested route paths build upon parent route paths, and nested route elements render inside parent route elements. See the note about <Outlet> below. */} <Routes> <Route path="/" element={<Layout />}> <Route index element={<Home />} /> <Route path="about" element={<About />} /> <Route path="dashboard" element={<Dashboard />} />
{/* Using path="*"" means "match anything", so this route acts like a catch-all for URLs that we don't have explicit routes for. */} <Route path="*" element={<NoMatch />} /> </Route> </Routes> </div> )}
function Layout() { return ( <div> {/* A "layout route" is a good place to put markup you want to share across all the pages on your site, like navigation. */} <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> <li> <Link to="/dashboard">Dashboard</Link> </li> <li> <Link to="/nothing-here">Nothing Here</Link> </li> </ul> </nav>
<hr />
{/* An <Outlet> renders whatever child route is currently active, so you can think about this <Outlet> as a placeholder for the child routes we defined above. */} <Outlet /> </div> )}
function Home() { return ( <div> <h2>Home</h2> </div> )}
function About() { return ( <div> <h2>About</h2> </div> )}
function Dashboard() { return ( <div> <h2>Dashboard</h2> </div> )}
function NoMatch() { return ( <div> <h2>Nothing to see here!</h2> <p> <Link to="/">Go to the home page</Link> </p> </div> )}
createBrowserRouter
การสร้าง Route แบบใช้ createBrowserRouter
จะลองรับพวก Data API พวก loaders, actions, fetchers ด้วย แต่ว่าขอไม่พูดถึงละกัน ใครอยากรู้ลองไปอ่าน Tutorial ดูได้ครับ
การสร้างแบบนี้ ก็คล้ายๆ แบบแรก เพราะจริงๆ แบบแรก มันก็จะแปลงเป็น Object ลักษณะคล้ายๆกันนี่แหละ
สร้าง Router ขึ้นมาก่อน โดยกำหนดเป็น object array ที่เราต้องการ กำหนด path, element หรือ children เหมือนกับ <Route>
component เลย
import { createBrowserRouter } from 'react-router-dom'
const router = createBrowserRouter([ { path: '/', element: <Layout />, children: [ { path: '/', index: true, element: <Home /> }, { path: 'about', element: <About /> }, { path: 'dashboard', element: <Dashboard /> }, { path: '*', element: <NoMatch /> } ] }])
ส่วน Main.tsx
ก็แค่เปลี่ยนจาก BrowserRouter เป็น <RouterProvider>
แทน แบบนี้
import { RouterProvider } from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root')!).render(
{' '}
<React.StrictMode> <RouterProvider router={router} /></React.StrictMode>)
ผลลัพธ์ที่ได้ก็จะเหมือนแบบแรก
ลองไปอ่านเพิ่มเติม ฝึกเล่น ฝึกลองเขียนกันดูนะครับ (แต่จริงๆ ส่วนตัวผมมองว่า รู้แค่หลักการและวิธีการใช้งานก็พอ โอกาสที่จะใช้งาน React Router ก็คงต้องเป็นงานเฉพาะ ที่ไม่ได้ต้องการเรื่อง SEO เท่าไหร่ อาจจะเป็นหน้า Dashboard หรือระบบภายในมากกว่า)
เพราะถ้าทำระบบปัจจุบัน มี SEO เน้น Server Side ด้วย ผมมองว่า ก็ไปทาง Next.js เลย เพราะสุดท้าย ถ้าเราไม่ต้องการ Server Side ตัว Next.js ก็ build แค่ static file ให้เป็น Client Side ก็ได้เช่นกัน
Happy Coding ❤️
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust