บันทึกสั้นๆ เผื่อได้ใช้ React Router v6 (Alpha)
วันนี้จะมาบันทึกการลองใช้งาน 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% เลยครับ
จาก 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 as>
ข้อนี้แค่เปลี่ยนจาก <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 />} />
navigation
ใน 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
- Authors
- Name
- Chai Phonbopit
- Website
- @Phonbopit