Обзор текущего состояния Next.js Router



Книга Обзор текущего состояния Next.js Router

Фреймворк Next.js динамично развивается, он сделал огромный скачок вперед, и поэтому многие предыдущие статьи о нем могли устареть. На момент написания этой статьи действует версия 10.2.3. Предлагаю заглядывать в документацию при использовании примеров, так как некоторые рекомендации могут устаревать из-за улучшившегося API.


Появился функционал, о котором вы можете не знать


У тех из вас, кто давно использует Next.js, в проектах наверняка накопился огромный объем кода, и вы просто продолжаете писать его в уже сложившемся стиле. Одни делают это в силу привычки, другие  —  потому что используют свою кодовую базу в качестве каталога фрагментов кода и примеров. Поэтому они рискуют упустить из виду новые крутые функциональные возможности.


Перенаправления сервера и статус «не найдено»



JavaMentor


JavaMentor

Эти функциональные возможности, как и предыдущие, появились в версии 10. Однако до сих пор возникает много вопросов о том, как сделать перенаправление на сервере. Рекомендую первым делом проверить, используете ли вы современные методы получения данных, потому что только они обновляются и получают новые функциональные возможности.


Вот простой способ сделать перенаправление или показать страницу 404:


// Перенаправление
export function getServerSideProps() {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}

// Страница 404
export function getServerSideProps() {
return {
notFound: true,
}
}

Автоматическое разрешение параметра href


Попробуйте найти в своем проекте next/link, где есть href, а также свойство as. Нашли? Тогда пора обновить эти ссылки. Потому что, начиная с версии 10.x, больше не нужно передавать оба эти параметра. Удалите параметр href и переименуйте as в href: работать будет так же хорошо.


import Link from 'next/link'

// Как было
function MyComponent() {
return (
<Link href="/posts/[post]" as="/posts/blog-post">
Blog post
</Link>
)
}

// Начиная с версии v10.x
function MyComponent() {
return <Link href="/posts/blog-post">Blog post</Link>
}

Функции маршрутизатора клиента


Заметил, что люди часто используют router.push из useRouter. Тоже это делаете в функциях, обернутых в useCallback, или просто внутри useEffect? Тогда придется упомянуть об этом в зависимостях, как в следующем примере:


// pages/params.jsx
import { useEffect, useCallback } from 'react'
import { useRouter } from 'next/router'

function MyComponent() {
const { push } = useRouter()
const handleClick = useCallback(() => {
// какая-то логика
push('/profile')
}, [push])

useEffect(() => {
if (...) {
push('/sign-in')
}
}, [push])

return <>...</>
}

Но это совершенно необязательно, потому что эти функции не обновляются через повторные отображения, зато правила ESLint будут вынуждать вас это делать. Решения здесь довольно простые: использовать функции маршрутизации из Router. Это сделает ваш код чище и приятнее. 😉


// pages/params.jsx
import Router from 'next/router'

function MyComponent() {
const handleClick = useCallback(() => {
// какая-то логика
Router.push('/profile')
}, [])

useEffect(() => {
if (...) {
Router.push('/sign-in')
}
}, [])

return <>...</>
}

Иногда при работе с маршрутизатором нужно получить текущее имя пути. Но у react/router в этом поле хранится динамическое представление маршрутизатора, и оно совпадает с полем маршрутизатора. Тогда создаем эти параметры самостоятельно помощью asPath. Я сделал обертку поверх useRouter и всегда имею доступ к свойствам, когда они мне нужны.


// lib/router.js
import { useRouter as useNextRouter } from 'next/router'

export function useRouter() {
const router = useNextRouter()
const [pathname, queryString = ''] = router.asPath.split('?')

return Object.assign(router, { pathname, queryString })
}

Обертка предоставляет удобные свойства, которые используются в ситуации, когда нужно обновить текущий маршрут.


// pages/params.jsx
import Router from 'next/router'
import { useRouter } from 'lib/router'

function MyComponent() {
const { query, pathname } = useRouter()

function handleSubmit(evt) {
const params = new FormData(evt.currentTarget).getAll("fruits");
evt.preventDefault();
Router.replace(
{ pathname, query: { ...query, params }},
null,
{ shallow: true }
)
}

return (
<form>
{...}
<button type="submit">Apply</button>
</form>
)
}

А знаете, почему второй параметр в Router.replace имеет значение null? Начиная с версии 10.x, благодаря автоматическому разрешению есть возможность этот параметр пропустить.


Имея такую функциональную возможность, как автоматическое разрешение, было бы естественно задействовать ее в next/router, но это маленько неудобно в API. Ведь, когда требуется передать опции options, следует передавать динамический маршрут в первый аргумент и полный путь во второй в более ранних версиях, а в Next.js эти три аргумента сохранялись для обратной совместимости. Хорошо, что есть небольшие удобные функции, которые упрощают использование функций маршрутизатора:


// lib/router.js
import NextRouter from 'next/router'

function push(url, opts) {
return NextRouter.push(url, null, opts)
}

const Router = {
...NextRouter,
push,
}

export default Router

// pages/params.jsx
import Router, { useRouter } from 'lib/router'

function MyComponent() {
const { query } = useRouter()

function handleSubmit(evt) {
const params = new FormData(evt.currentTarget).getAll("fruits");

evt.preventDefault();
Router.push({ pathname, query: { ...query, params } }, { shallow: true });
}

return <>{...}</>
}

Заключение


Спасибо, что дочитали статью до конца. Полный код найдете на GitHub. Всегда есть способ улучшить хорошие инструменты. А небольшие улучшения способны здорово помочь разработчику и его проекту.


855   0  

Comments

    Ничего не найдено.