Поиск по сайту:

Краткий обзор React Router v6


На момент написания этой статьи React Router v6 все еще находится в стадии альфа-тестирования, но самое время начать играть с ним и исследовать, что будет дальше. Это руководство познакомит вас с новыми функциями/изменениями!

Как вы, возможно, знаете, в начале 2018 года ведущие разработчики разветвили Reach Router.

За это время обе библиотеки выросли, однако похоже, что активная разработка Reach Router прекратится и будет объединена с грядущей версией React Router v6 🛣

Скоро релиз, вот краткий обзор того, что будет!

Перейти к…

  • становится
  • Большие изменения с
  • Вложенные маршруты проще
  • useNavigate вместо useHistory
  • От 20 КБ до 8 КБ

становится

Этот компонент верхнего уровня будет переименован. Тем не менее, его функциональность в основном остается прежней.

// v5
import {
  BrowserRouter,
  Switch,
  Route
} from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/"><Home /></Route>
        <Route path="/profile"><Profile /></Route>
      </Switch>
    </BrowserRouter>
  );
}

Просто поместите туда :

// v6
import {
  BrowserRouter,
  Routes,
  Route
} from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="profile/*" element={<Profile />} />
      </Routes>
    </BrowserRouter>
  );
}

Большие изменения с

В версии 6 компонент претерпевает наибольшие изменения. К счастью, эти новые изменения упростят использование!

Свойство component/render будет заменено на свойство element:

import Profile from './Profile';

// v5
<Route path=":userId" component={Profile} />
<Route
  path=":userId"
  render={routeProps => (
    <Profile routeProps={routeProps} animate={true} />
  )}
/>

// v6
<Route path=":userId" element={<Profile />} />
<Route path=":userId" element={<Profile animate={true} />} />

Если вы заметили, в версии 6 стало намного проще передавать пропсы. Это свело на нет использование реквизита render в v5.

Вложенные маршруты проще

Вложенные маршруты в v5 должны были быть очень явно определены. Это потребовало включения в эти компоненты большого количества логики сопоставления строк. См. :

// v5
import {
  BrowserRouter,
  Switch,
  Route,
  Link,
  useRouteMatch
} from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/profile" component={Profile} />
      </Switch>
    </BrowserRouter>
  );
}

function Profile() {

  let match = useRouteMatch();

  return (
    <div>
      <nav>
        <Link to={`${match.url}/me`}>My Profile</Link>
      </nav>

      <Switch>
        <Route path={`${match.path}/me`}>
          <MyProfile />
        </Route>
        <Route path={`${match.path}/:id`}>
          <OthersProfile />
        </Route>
      </Switch>
    </div>
  );
}

В v6 вы можете удалить логику сопоставления строк. Также нет необходимости в useRouteMatch()! Результат приятно минимален:

// v6
import {
  BrowserRouter,
  Routes,
  Route,
  Link,
  Outlet
} from 'react-router-dom';

// Approach #1
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="profile/*" element={<Profile/>} />
      </Routes>
    </BrowserRouter>
  );
}

function Profile() {
  return (
    <div>
      <nav>
        <Link to="me">My Profile</Link>
      </nav>

      <Routes>
        <Route path="me" element={<MyProfile />} />
        <Route path=":id" element={<OthersProfile />} />
      </Routes>
    </div>
  );
}

// Approach #2
// You can also define all
// <Route> in a single place
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="profile" element={<Profile />}>
          <Route path=":id" element={<MyProfile />} />
          <Route path="me" element={<OthersProfile />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

function Profile() {
  return (
    <div>
      <nav>
        <Link to="me">My Profile</Link>
      </nav>

      <Outlet />
    </div>
  )
}

Примечание. Компонент используется как {this.props.children} в React Router v6. Это была очень популярная функция Reach Router!

useNavigate вместо useHistory

Иногда вам может понадобиться программная навигация. Например, после того, как пользователь отправляет форму, его необходимо перенаправить на страницу подтверждения. Это библиотека useHistory в версии 5, которая была переименована в useNavigate в версии 6:

// v5
import { useHistory } from 'react-router-dom';

function MyButton() {
  let history = useHistory();
  function handleClick() {
    history.push('/home');
  };
  return <button onClick={handleClick}>Submit</button>;
};

Теперь history.push() будет заменен на navigate():

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

function MyButton() {
  let navigate = useNavigate();
  function handleClick() {
    navigate('/home');
  };
  return <button onClick={handleClick}>Submit</button>;
};

В некоторых случаях вам может потребоваться заменить URL-адрес в истории браузера вместо того, чтобы вводить новый URL-адрес. Это немного изменилось с v6:

// v5
history.push('/home');
history.replace('/home');

// v6
navigate('/home');
navigate('/home', {replace: true});

От 20кб до 8кб

Со всеми этими изменениями вы ожидаете, что размер пакета вырастет, но на самом деле он уменьшился вдвое! Минимизированный пакет v5 весил ~20 КБ, а v6 — всего ~8 КБ.

Размеры пакетов рассчитываются с помощью инструмента BundlePhobia.

Заключение

Я очень рад выпуску React Router v6. Надеюсь, эта статья дала вам представление о том, чего ожидать, когда он выйдет (что должно произойти в ближайшее время)! Вы можете узнать больше о React Router v6 в последних примечаниях к выпуску 📝

Полный список новых функций см. в официальном руководстве по миграции React Router v6 🚏