З п'ятою версією React Router з'являється підтримка хуків, за допомогою яких можна керувати роутингом.
Цей матеріал буде корисним для тих, хто хоче швидко ознайомитись з особливостями нового React Router. Але перше ніж перейти до хуків, оглянемо новий патерн рендерингу роутів.
До появи React Router 5
// Коли треба було відрендерити роут та передати пропси роутера в компонент
<Route path="/" component={Home} />
// Або коли треба було передати додаткові пропси
<Route path="/" render={({ match }) => <Profile match={match} mine={true} />}>
Коли ми використовували параметр component
для рендерингу відповідного компонента, пропси роутера match
, location
та history
передавались йому автоматично. Однак для передачі додаткових параметрів, необхідно було використати render
.
Варто пам'ятати, передана до параметра component
функція спричинить повторне монтування компонента при кожному рендерингу.
Після появи React Router 5
<Route path="/">
<Home />
</Route>
Зверніть увагу на відсутність додаткових параметрів в компоненті Home
. Тепер ви можете, не змінюючи компонент Route
, передати будь-які додаткові пропси дочірньому компоненту. До того ж автоматично виправляється проблема з повторним монтуванням компонента при кожному рендері.
Але ж тепер пропси роутера не передаються неявно. То як нам отримати доступ до match
, location
та history
? Чи треба тепер огортати всі компоненти withRouter
? Тут на допомогу і приходять хуки.
Зверніть увагу, що хуки було запропоновано у версії React 16.8, тож перевірте версію React у вашому проєкті, перш ніж використовувати їх.
useHistory
- Хук дає доступ до параметра
history
React Router. - Належить до history package: залежності, яку використовує сам роутер.
- Основне застосування — роутинг, який задається явно за допомогою
push
,replace
тощо.
import { useHistory } from 'react-router-dom';
function Home() {
const history = useHistory();
return <button onClick={() => history.push('/profile')}>Profile</button>;
}
useLocation
- Хук дає доступ до параметра
location
React Router. - Працює подібно до параметра нативного об'єкта браузера
window
—window.location
, однак доступний всюди та передає стан роутера та поточне розташування. - Основний варіант використання — отримання параметрів запиту з рядка маршруту.
import { useLocation } from 'react-router-dom';
function Profile() {
const location = useLocation();
useEffect(() => {
const currentPath = location.pathname;
const searchParams = new URLSearchParams(location.search);
}, [location]);
return <p>Profile</p>;
}
Оскільки властивість location
незмінювана, useEffect
викликатиме передану функцію кожного разу, коли змінюється роут. А це чудова можливість керувати параметрами пошуку або поточним шляхом.
useParams
- Хук дає доступ до параметрів пошуку в URL;
- Раніше так можна було лише з
match.params
;
import { useParams, Route } from 'react-router-dom';
function Profile() {
const { name } = useParams();
return <p>{name}'s Profile</p>;
}
function Dashboard() {
return (
<>
<nav>
<Link to={`/profile/ann`}>Ann's Profile</Link>
</nav>
<main>
<Route path="/profile/:name">
<Profile />
</Route>
</main>
</>
);
}
useRouteMatch
- Хук дає доступ до об'єкта
match
; - Якщо використовувати його без аргументів, він повертає найточніший збіг серед роутів компонента або його батьківських компонентів;
- Основний варіант використання — створення вкладених маршрутів.
import { useRouteMatch, Route } from 'react-router-dom';
function Auth() {
const match = useRouteMatch();
return (
<>
<Route path={`${match.url}/login`}>
<Login />
</Route>
<Route path={`${match.url}/register`}>
<Register />
</Route>
</>
);
}
Ви також можете використовувати useRouteMatch
для доступу до збігу маршруту, не рендеривши Route
. Для цього передайте в хук аргумент поточного маршруту.
Уявіть, що вам необхідно, аби власний профіль користувача рендерився на роуті /profile
, а роут профілю інших користувачів містив їхнє ім'я, наприклад: /profile/dan
, /profile/ann
. До появи хуків для цього ми використовували Switch
, щоб перелічити обидва роути та налаштувати їхню поведінку за допомогою пропсів. Але погляньте, наскільки просто це реалізувати за допомогою нових хуків.
import {
Route,
BrowserRouter as Router,
Link,
useRouteMatch,
} from 'react-router-dom';
function Profile() {
const match = useRouteMatch('/profile/:name');
return match ? <p>{match.params.name}'s Profile</p> : <p>My own profile</p>;
}
export default function App() {
return (
<Router>
<nav>
<Link to="/profile">My Profile</Link>
<br />
<Link to={`/profile/ann`}>Ann's Profile</Link>
</nav>
<Route path="/profile">
<Profile />
</Route>
</Router>
);
}
Ви досі можете використовувати всі пропси в Route
— на зразок exact
та sensitive
— як параметри об'єкта в useRouteMatch
.
Висновок
Хуки та явні компоненти Route
мають переваги, яких не видно на перший погляд. Однак після використання їх в реальних проєктах можна побачити, що це краще за попередні шаблони, котрі були в роутингу.
З хуками ваш код для роутингу стане більш підтримуваним, стійким до помилок та гнучким для нововведень в наступних версіях React Router.
Ще немає коментарів