Источник: Nuances of Programming
Фреймворк Next.js динамично развивается, он сделал огромный скачок вперед, и поэтому многие предыдущие статьи о нем могли устареть. На момент написания этой статьи действует версия 10.2.3. Предлагаю заглядывать в документацию при использовании примеров, так как некоторые рекомендации могут устаревать из-за улучшившегося API.
Появился функционал, о котором вы можете не знать
У тех из вас, кто давно использует Next.js, в проектах наверняка накопился огромный объем кода, и вы просто продолжаете писать его в уже сложившемся стиле. Одни делают это в силу привычки, другие — потому что используют свою кодовую базу в качестве каталога фрагментов кода и примеров. Поэтому они рискуют упустить из виду новые крутые функциональные возможности.
Перенаправления сервера и статус «не найдено»
Эти функциональные возможности, как и предыдущие, появились в версии 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 <>...</> }
// 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. Всегда есть способ улучшить хорошие инструменты. А небольшие улучшения способны здорово помочь разработчику и его проекту.
Читайте также:
Перевод статьи Pavel Mineev: An Overview on the Current State of Next.js Router