React Router, версия 6. Часть 4 из 4
23.12.2021
Теги: Frontend • JavaScript • React.js • Web-разработка • Маршрутизация • Модуль
useSearchParams
Хук useSearchParams
предназначен для чтения и изменения строки запроса в URL для текущего маршрута. По аналогии с хуком useState
возвращает значение и функцию для изменения этого значения. Значение — это объект URLSearchParams
, у которого множество методов для работы с GET-параметрами (get
, set
, getAll
, has
, append
, delete
, …), подробнее здесь.
const [searchParams, setSearchParams] = useSearchParams() for (let entry of searchParams.entries()) { console.log(entry[0] + '=' + entry[1]) } setSearchParams({hello: 'world'})
Давайте создадим две страницы PageOne
и PageTwo
, добавим ссылки на них в главное меню. На первой странице установим параметры запроса, а на второй — прочитаем эти параметры.
import { useNavigate, createSearchParams } from 'react-router-dom' const PageOne = () => { const navigate = useNavigate() const params = { from: 'OnePage', now: Date.now().toString() } const search = '?' + createSearchParams(params) const gotoPageTwo = () => { navigate({ pathname: '/page-two', search: search, }) } return ( <> <h1>Page One</h1> <button onClick={gotoPageTwo}>Go to Page Two</button> </> ) } export default PageOne
import { useSearchParams } from 'react-router-dom' const PageTwo = () => { const [searchParams, setSearchParams] = useSearchParams() const params = [] const search = {} for (let entry of searchParams.entries()) { params.push(entry[0] + '=' + entry[1]) search[entry[0]] = entry[1] } const appendParam = () => { setSearchParams({...search, rand: Math.random()}) } return ( <> <h1>Page Two</h1> <ul> {params.map(item => <li key={item}>{item}</li>)} </ul> <button onClick={appendParam}>Append param</button> </> ) } export default PageTwo
Исходные коды приложения здесь, директория 5.
Вложенные роуты
Мы уже работали с вложенными роутами — все роуты у нас вложены в <Route path="/">
, кроме того, есть вложенные роуты для Blog
и Service
. Давайте добавим две вложенные страницы для About
— это будут Company
и Out team
.
const Company = () => { return <h1>Company</h1> } export default Company
const OurTeam = () => { return <h1>Our team</h1> } export default OurTeam
import { Link, Route, Routes } from 'react-router-dom' import Company from './Company.js' import OurTeam from './OurTeam.js' const About = () => { return ( <> <h1>About page</h1> <ul> <li><Link to="company">Company</Link></li> <li><Link to="our-team">Our team</Link></li> </ul> <Routes> <Route path="company" element={<Company />} /> <Route path="our-team" element={<OurTeam />} /> </Routes> </> ) } export default About
Внесем изменения в компонент App.js
:
function App() { return ( <AuthProvider> <Routes> <Route path="/" element={<AppLayout />}> <Route index element={<Home />} /> .......... <Route path="about/*" element={<About />} /> .......... <Route path="*" element={<NotFound />} /> </Route> </Routes> </AuthProvider> ) }
Звездочка в атрибуте path
означает, что что по маршрутам about/company
и about/our-team
будет отрабатывать компонент About
. Но внутри About
может быть еще один компонент Routes
, который определяет маршруты относительно about
. Хотя так можно делать, но лучше вынести вложенные маршруты в компонент App
— чтобы все они были в одном месте.
import { Link, Outlet } from 'react-router-dom' const About = () => { return ( <> <h1>About page</h1> <ul> <li><Link to="company">Company</Link></li> <li><Link to="our-team">Our team</Link></li> </ul> <Outlet /> </> ) } export default About
function App() { return ( <AuthProvider> <Routes> <Route path="/" element={<AppLayout />}> <Route index element={<Home />} /> .......... <Route path="about" element={<About />}> <Route path="company" element={<Company />} /> <Route path="our-team" element={<OurTeam />} /> </Route> .......... <Route path="*" element={<NotFound />} /> </Route> </Routes> </AuthProvider> ) }
Исходные коды приложения здесь (директория app
), демо-сайт здесь.
useRoutes
Компонент Routes
является оберткой над useRoutes
, два фрагмента кода ниже эквивалентны.
function App() { return ( <Routes> <Route path="/" element={<AppLayout />}> <Route index element={<Home />} /> <Route path="about" element={<About />} /> <Route path="*" element={<NotFound />} /> </Route> </Routes> ) }
function App() { const element = useRoutes([ { path: '/', element: <AppLayout />, children: [ { index: true, element: <Home /> }, { path: 'about', element: <About /> }, { path: '*', element: <NotFound /> }, ] }, ]) return element }
Атрибут basename
Если приложение развернуто в подкаталоге на сервере, необходимо использовать атрибут basename
для BrowserRouter
.
import React from 'react' import ReactDOM from 'react-dom' import { BrowserRouter } from 'react-router-dom' import './index.css' import App from './App.js' ReactDOM.render( <React.StrictMode> <BrowserRouter basename="/react-router-app"> <App /> </BrowserRouter> </React.StrictMode>, document.getElementById('root') )
Дополнительно
Отличный мини-курс от Михаила Непомнящего на YouTube:
- Базовый роутинг React-приложения
- Общая разметка и компонент Outlet
- Компонент NavLink и его кастомизация
- Параметры в ссылках
- Работа с историей, локацией и приватными роутами
- Параметры поиска
- Вложенный роутинг
Поиск: Frontend • JavaScript • React.js • Web-разработка • Маршрутизация • Модуль