Next.js наступает на серию входов в яму
- (один)Hello Next.js
- (два)Добавить ИНТД && CSS
- (три)Рефакторинг каталога и повторная маршрутизация
- (Четыре)Среднесрочное наполнение Next.js
- (пятерки)Представляем Redux для управления состоянием
- (шесть)Рефакторинг каталога снова
- (Семь)Другие сопутствующие знания
получить данные && getInitialProps
Получение данных по-прежнему является разницей между Next и обычными приложениями React SPA.Приложения React в основном имеют свои собственные компоненты маршрутизации (конечно, большинство из них являются реактивными маршрутизаторами).Мы можем использовать методы, предоставляемые компонентами маршрутизации для нас, такие как react -router onEnter() или универсальный-маршрутизатор beforeEnter().
Здесь я рекомендую компонент маршрутизации, отличный от react-routeruniversal-router
А Next.js не имеет компонентов маршрутизации, поэтому конкретный метод определенно отличается от компонентов маршрутизации.Конкретное отличие заключается в том, что Next.js предоставляет нам новый жизненный цикл, отличный от React — getIntialProps(). это Великолепие API.
инструкции
- Использование в React.Component
import React from 'react'
export default class extends React.Component {
static async getInitialProps({ req }) {
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
return { userAgent }
}
render() {
return (
<div>
Hello World {this.props.userAgent}
</div>
)
}
}
- Использование внутри компонентов без сохранения состояния
const Page = ({ stars }) =>
<div>
Next stars: {stars}
</div>
Page.getInitialProps = async ({ req }) => {
const res = await fetch('https://api.github.com/repos/zeit/next.js');
const json = await res.json();
return { stars: json.stargazers_count };
}
export default Page;
Этот жизненный цикл отделен от обычного жизненного цикла React, но мы по-прежнему можем использовать различные функции жизненного цикла компонента реакции в компоненте.
сервер доступен
Это действительно преимущество жизненного цикла getInitialProps.Он может работать на стороне сервера.Какая польза от этого? Честно говоря, я действительно не знаю, я знаю только немного, я расскажу об этом позже, ха-ха. Если кто-то знает об этом, вы можете оставить сообщение и рассказать мне~ Нечего сказать, картинка выше:
Как видите, в этом жизненном цикле я инициировал действие для получения данных, и это действие было напечатано на консоли, что указывает на то, что оно может выполняться на стороне сервера~
Сократите количество циклов очистки данных
-
Получить данные в старом жизненном цикле React
Возьмем в качестве примера захват списка пользователей, мы можем получить его в жизненном цикле componentDidMount в компоненте
// /components/user/userList.js
...
componentDidMount() {
this.props.fetchUserList();
}
Из приведенного выше рисунка видно, что каждый раз, когда мы заходим на страницу со списком пользователей, пользовательские данные будут повторно извлекаться. Кто-то может сказать, разве это не ерунда, нельзя так реагировать, маршрутизация была переключена. Правильно, так и должно быть в норме, поэтому новый жизненный цикл Next.js великолепен.
- Использование жизненного цикла getInitialProps
// /pages/user/userList.js
import UserList from '../../containers/user/UserList';
import { fetchUserListData } from '../../redux/actions/user';
UserList.getInitialProps = async (props) => {
const { store, isServer } = props.ctx;
if (store.getState().user.list.list.length === 0) {
store.dispatch(fetchUserListData());
}
return { isServer };
};
export default UserList;
Братцы, посмотрите на картинку выше и убедитесь, что вы не обнаружите, что после входа в систему вы получите данные только при вводе маршрута в первый раз, а затем снова войти, потому что сервер закешировал данные, поэтому нет необходимости повторно приобретать его, что снижает количество приобретений~
Конкретная причина заключается в том, что жизненный цикл статического getInitialProps() может быть запущен на стороне сервера.Когда страница загружается в первый раз, сервер получает запрос, getInitialProps() будет выполнен, и данные, возвращаемые getInitialProps () будет сериализован и добавлен прибыть
window.__NEXT_DATA__.props
, написанный в исходном коде HTML, аналогичный ={props:{xxx}}. Таким образом, getInitialProps() на стороне сервера осуществляет передачу данных клиенту. Когда мы переходим на страницу через ссылку маршрутизации Next.js, клиент получает данные из window.__NEXT_DATA__ для отображения страницы, и нет необходимости повторно извлекать данные. Это способ повысить производительность~ Как показано на рисунке ниже Показать:
Есть проблема - наступить на яму
Здесь на самом деле яма, может быть, многие сталкивались с ней, а может быть, никто не сталкивался. Конкретная проблема описывается так.Предварительно выбираем данные в getInitialProps.На примере списка пользователей при загрузке в первый раз проблем нет, в том числе и при различных скачках клиента. Однако, когда мы обновим страницу со списком пользователей, на самом деле он не проходит жизненный цикл getInitialProps, поэтому на странице не будет данных, которые можно отобразить, и появится пустая страница, потому что он думает, что это должно быть из window.__Next_DATA__.Get вместо повторного получения данных~ Тогда почему вы не зашли в getIntialProps после обновления страницы?Честно говоря, я действительно не совсем понял, но обновление страницы next.js вернет нам isServer: true в реквизитах, но контрольная станция не получила данные. Смотрите скриншот ниже для конкретных вопросов:
На скриншоте хорошо видно, что данные страницы получены через redux-saga, в getIntialProps() страниц код такой:
import { fetchUserListData } from '../../redux/actions/user';
UserList.getInitialProps = async (props) => {
const { store, isServer } = props.ctx;
if (store.getState().user.list.list.length === 0) {
store.dispatch(fetchUserListData());
}
return { isServer };
};
Вышеприведенный fetchUserListData() — это действие для захвата данных, возвращаемое значение будет сохранено в состоянии, а список данных будет отображен. Очевидно, что выборка прошла успешно при первой загрузке. Но после обновления страницы нет действия отправки, а это значит, что обновление страницы не проходит через жизненный цикл getIntialProps! ! !
Вышеизложенное является ключевой проблемой. Это нормально без обновления страницы. Обновление страницы не проходит этот жизненный цикл, и многие наши данные должны быть предварительно извлечены, поэтому это настоящая яма. На самом деле, многие люди столкнуться с этой проблемой, и я также нашел эту проблему в демо-версии reudx, предоставленной следующим официальным лицом, что означает, что их официальное демо-обновление также будет иметь эту проблему.
Решение
Поскольку он наступает на яму, конечно, есть решение ~ и есть два вида:
-
Первый: судить isServer в жизненном цикле компонента
Проблема только что описана, то есть нормальная загрузка и скачки страниц через роутинг, данные будут нормально отрисовываться и получаться из окна браузера.__NEXT_DATA__ для уменьшения лишних сетевых запросов~, но не при обновлении страницы. данные, и мы не можем найти нужные данные в окне.__NEXT_DATA__. Однако через консольную информацию мы можем найти проблему и решение. То есть при первом запуске системы isServer возвращает false, а когда браузер обновляет страницу, isServer возвращает true.Мы можем судить об этой переменной в компоненте.Если она истинна, пересхватываем данные Выбрать.
// /components/user/UserList.js
...
componentDidMount() {
if(this.props.isServer) {
// 需要重新抓取数据
this.props.fetchUserListData();
}
}
...
Как видно из приведенного выше рисунка, когда страница обновляется, мы повторно извлекаем данные для отображения страницы, и они не будут повторно извлекаться, если не будут обновлены. Так еще можно...
-
Второй: еще один способ предварительной выборки данных
Другой метод более продвинутый.Я до сих пор не знаю принципа, но им легко пользоваться.Ха-ха,эта штука реально злая.Почему ты так говоришь? В частности, в приведенном выше письме я написал действие отправки в getInitalProps для получения данных.Как вы можете видеть из предыдущего раздела или кода, это действие фактически извлекает API для получения данных и возврата состояния. Это базовый процесс получения данных для редукции. Этот метод не работает при обновлении, но работает метод: вместо получения данных через действие отправки он напрямую получает данные через fetch API в getIntialProps. Таким образом, данные можно получать каждый раз при обновлении страницы. . . Это так удивительно, и я действительно не знаю, почему.
// /pages/user/userList
import fetch from 'isomorphic-unfetch';
import UserList from '../../containers/user/UserList';
import { fetchUserListDataSuccess } from '../../redux/actions/user';
UserList.getInitialProps = async (props) => {
const { store, isServer } = props.ctx;
let userData;
if (store.getState().user.list.list.length === 0) {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
userData = await res.json();
store.dispatch(fetchUserListDataSuccess(userData));
}
return { isServer };
};
export default UserList;
Удивительно, что есть лес. Честно говоря, я действительно не знаю, почему. Если есть большая корова, я очень ценю это~
Тем не менее, я по-прежнему предпочитаю первый из приведенных выше, потому что я думаю, что первый находится под моим контролем, потому что я писал реактивный проект для управления получением некоторых данных в жизненном цикле. Может и привычнее, но допускаю, что второй вид мощнее, да и производительность может лучше ~ бери что надо.
Document
С точки зрения моего использования, функция этого компонента такая же, как и назначение предыдущих глав, то есть у нас нет index.html в Next.js аналогично create-react-app. Таким образом, у нас нет возможности определить структуру окончательно отображаемого html, например заголовок, метатеги и другие теги. Сначала я реализовал это через компонент Head в next/head, но компонент head фактически генерирует тег html head в конце. Компонент Document полностью помогает нам построить HTML-структуру.
// 除去Layout的Head结构
// pages文件夹新增_document.js文件
// ./pages/_document.js
import Document, { Head, Main, NextScript } from 'next/document';
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<html>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1' />
<meta charSet='utf-8' />
<title>Next-Antd-Scafflod</title>
<link rel='shortcut icon' href='/static/favicon.ico' type='image/ico'/>
<link rel='stylesheet' href='/_next/static/style.css' />
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
);
}
}
_document.js отображается только на стороне сервера Next.js. Клиент получает только строку HTML, отображаемую на стороне сервера для отображения страницы интерфейса. Упомянутое выше окно.__NEXT_DATA__ хранится в NextScript.
Dynamic Import
На самом деле, я сталкивался со многими ловушками при написании проектов рендеринга на стороне сервера. Наиболее распространенной из них является то, что я хочу ввести некоторые внешние компоненты.У этих компонентов есть переменные на стороне клиента, такие как окно и документ, и эти переменные не включены. на стороне сервера.Он существует, поэтому он будет сообщать об ошибке при рендеринге на стороне сервера, поэтому это очень хлопотно, требует различных конфигураций веб-пакета, а затем вводит его асинхронно. Например: редактор форматированного текста. А следующий непосредственно инкапсулирует для нас динамически вводимый импорт, это должен быть метод импорта вебпака, который неожиданно не используется. Ниже приведена простая демонстрация одной из функций, которая заключается в динамическом представлении редактора форматированного текста, а затем загрузке другого компонента в пустой период.Использование очень простое, как показано ниже:
import dynamic from 'next/dynamic';
const DynamicComponent = dynamic(import('braft-editor'), {
loading: () => <p>正在加载组件...</p>
});
render() {
return (
<Fragment>
<h1>用户信息:{this.state.username}</h1>
<div style={{ width: '50%', height: '400px', }}>
<DynamicComponent />
</div>
</Fragment>
);
}
Подробный Next предоставляет нам больше методов.Если вам интересно, вы можете перейти на официальный сайт, чтобы увидеть документацию.Есть четыре метода асинхронного введения, включая только введение на стороне сервера~адрес документа
error handling
Обработка ошибок.В настоящее время многие отличные скаффолды предоставляют нам обработку ошибок, например, рендеринг страницы на 404 и 500. Точно так же Next.js автоматически инкапсулирует для нас errorPage внутри. То есть нам не нужно ничего делать, чтобы пользоваться этой услугой. Например, если я случайно введу URL-адрес в систему, появятся следующие результаты:
Затем вы также можете определить свою страницу errorPage самостоятельно.Метод очень прост, то есть создайте новый файл _error.js в папке pages и напишите в нем свой код errorPage.Взято с официального сайта~
// /pages/_error.js
import React from 'react'
export default class Error extends React.Component {
static getInitialProps({ res, err }) {
const statusCode = res ? res.statusCode : err ? err.statusCode : null;
return { statusCode }
}
render() {
return (
<p>
{this.props.statusCode
? `An error ${this.props.statusCode} occurred on server`
: 'An error occurred on client'}
</p>
)
}
}
хорошо, вы можете видеть, что это очевидно эффективно. Хотя эффект похож, если писать по своему, то точно не проблема. ха-ха~
Static HTML export
Еще одна продвинутая функция, она помогает нам экспортировать различные маршруты в статические страницы, но если подумать, это не очень полезно, ведь наши проекты все логичны, и экспортом статических страниц управлять нельзя, ха-ха. Но так как это довольно крутая функция, давайте попробуем.
- Первый шаг — настроить страницы и маршруты в папке config.
exportPathMap: async (defaultPathMap) => {
return {
'/home': { page: '/' },
'/userList': { page: '/user/userList' },
}
},
- Второй шаг, package.json добавляет команду экспорта
"scripts": {
...
// 新增导出命令
"export": "yarn build && next export"
},
-
Третий шаг, запустите команду экспорта пряжи
После запуска команды в корневом каталоге появится папка out, что действительно удивительно, с папками страниц и необходимыми статическими ресурсами в ней.
Затем мы открываем index.html и посещаем его, это должна быть наша домашняя страница, домашняя страница выглядит так.эмм ... эта домашняя страница немного странная, статические ресурсы и css не совсем подходят, почему я не преследую ее, должен быть способ. Но я просто пробую функцию, время ограничено и готов отдохнуть, ха-ха. Всем, кто заинтересован в проведении собственных исследований.
Также есть продвинутый проект Next.js для выталкивания функции на страницу гитхаба, который тоже зависит от этого экспорта, но я не писал о проблеме времени.Если вам интересно, посмотрите официальную демку, она должна быть в состоянии решить ~
Суммировать
На этом этап Next.js по входу в яму завершен. Большое спасибо за многих друзей, которые смотрели, и некоторых милых друзей, которые настаивают на обновлениях.Уровень ограничен, и это полностью набор ловушек.Если это может помочь всем, я буду очень счастлив. Спасибо всем за чтение. Затем подготовьте веб-сайт с помощью Next.js. После завершения я могу написать еще одну статью о создании веб-сайта Next.js, и я не буду писать другие, а затем напишу другой контент ~
Кодовый адрес этой главы
Код проекта, дайте звезду, если вам это нравится, спасибо Минасанг