Автор Мохаммад Фейсал✏️
Redux — одно из самых популярных решений для управления состояниями в экосистеме React. В настоящее время существует множество альтернатив, но Redux по-прежнему остается самым надежным и широко используемым инструментом.
По этой причине многие проекты, использующие Next.js, хотят воспользоваться преимуществами Redux. Но использование Redux в приложении Next имеет несколько особенностей, и настройка не всегда проста. Поэтому в этой статье мы расскажем вам о том, как настроить проект Next с Redux.
- Содержание
- Почему вы должны использовать Redux с Next.js?
- Совместное использование состояния
- Redux очень мощный
- Все знают Redux
- Создание примера приложения с Next.js и Redux
- Установка зависимостей
- Создание фрагмента
- Создание хранилища
- Обновление приложения
- Использование магазина Redux
- Сохранение состояния в Next.js
- Заключение
- LogRocket: Полная видимость производственных приложений Next.js
Содержание
- Почему вы должны использовать Redux с Next.js?
- Создание примера приложения с Next.js и Redux
- Использование хранилища Redux
- Сохранение состояния в Next.js
Почему вы должны использовать Redux с Next.js?
Существует множество причин, по которым вы можете захотеть использовать Redux в приложении Next. Давайте рассмотрим некоторые из них.
Совместное использование состояния
Обычно центральное состояние используется для управления общими данными между компонентами в дереве. В React данные передаются только вниз, что означает, что вы можете передать данные от родительского компонента к дочернему компоненту.
Это ограничение иногда усложняет работу, поскольку компоненты могут находиться не рядом в дереве компонентов, и даже может не быть пути от родителя к ребенку.
В этом случае использование общего хранилища, в которое оборачиваются все компоненты, имеет полный смысл, и вы можете рассмотреть Redux.
Redux очень мощный
Redux очень силен как решение для управления состоянием. Он существует уже давно, поэтому имеет отличную поддержку сообщества.
Если вы создаете что-то серьезное и не знаете, какие сценарии использования могут появиться в будущем, скорее всего, у Redux найдется решение для вас. Несмотря на то, что ничто не может быть полностью защищено от будущего, Redux — это надежная ставка для долгосрочных проектов.
Все знают Redux
Во многих проектах скорость часто является приоритетом. Многие разработчики React уже знакомы с Redux, и компании часто хотят использовать один и тот же инструмент во всех проектах, если это возможно.
Это означает, что даже если вы работаете в компании, которая создает новый проект на Next, вас все равно могут заставить использовать Redux, так что будет хорошей идеей научиться использовать его, исходя только из популярности.
Создание примера приложения с Next.js и Redux
Сегодня мы создадим простое приложение, которое отслеживает, вошел ли пользователь в систему или нет, а затем, исходя из этого состояния, изменяет текст над кнопкой.
Цель этого проекта — продемонстрировать, как использовать Redux, поэтому я упрощаю задачу, чтобы мы могли сосредоточиться на интеграции Redux с Next. Далее у нас есть два варианта. Мы можем использовать обычный Redux, или мы можем использовать Redux Toolkit.
Redux используется во многих старых проектах, но рекомендуется использовать Redux Toolkit, так как в нем сокращено большое количество шаблонного кода и улучшена производительность. Однако настройки для обоих вариантов практически одинаковы.
Давайте создадим стартовый проект, выполнив следующую команду:
yarn create next-app --typescript
Вы можете увидеть проект в действии, запустив yarn dev
и посетив http://localhost:3000/ в браузере.
Установка зависимостей
Давайте установим необходимые зависимости для Redux Toolkit:
yarn add @reduxjs/toolkit react-redux
Поскольку мы используем Next, нам понадобится дополнительный пакет, который позаботится о рендеринге на стороне сервера:
yarn add next-redux-wrapper
Создание фрагмента
Давайте создадим новую папку store
и создадим в ней файл authSlice.ts
. В официальной документации слайс определяется как: «набор логики и действий Redux reducer для одной функции в вашем приложении».
Мы поместим логику для нашего authState
внутри этого файла authSlice.ts
:
import { createSlice } from "@reduxjs/toolkit";
import { AppState } from "./store";
import { HYDRATE } from "next-redux-wrapper";
// Type for our state
export interface AuthState {
authState: boolean;
}
// Initial state
const initialState: AuthState = {
authState: false,
};
// Actual Slice
export const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
// Action to set the authentication status
setAuthState(state, action) {
state.authState = action.payload;
},
// Special reducer for hydrating the state. Special case for next-redux-wrapper
extraReducers: {
[HYDRATE]: (state, action) => {
return {
...state,
...action.payload.auth,
};
},
},
},
});
export const { setAuthState } = authSlice.actions;
export const selectAuthState = (state: AppState) => state.auth.authState;
export default authSlice.reducer;
Это простой фрагмент. Слайс для любого обычного React-приложения, использующего Redux, будет выглядеть именно так. Для Next пока нет ничего особенного.
Единственное, что мы здесь делаем, это определяем authState
в нашем магазине и создаем действие для установки authState
под названием setAuthState
.
В строке 27 вы заметите специальный редуктор, который мы добавляем сюда под названием HYDRATE
. Обработчик действия HYDRATE
должен правильно согласовать гидратированное состояние поверх существующего состояния (если таковое имеется).
В принципе, когда происходит обновление страницы, если вы переходите с одной страницы на другую, или вызываются функции getStaticProps
или getServerSideProps
, в этот момент будет отправлено действие HYDRATE
. payload
этого действия будет содержать состояние на момент генерации статики или рендеринга на стороне сервера, поэтому ваш reducer должен правильно объединить его с существующим состоянием клиента.
Создание хранилища
Далее создайте файл store.ts
для создания магазина и добавьте туда наш authSlice
:
import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit";
import { authSlice } from "./authSlice";
import { createWrapper } from "next-redux-wrapper";
const makeStore = () =>
configureStore({
reducer: {
[authSlice.name]: authSlice.reducer,
},
devTools: true,
});
export type AppStore = ReturnType<typeof makeStore>;
export type AppState = ReturnType<AppStore["getState"]>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
AppState,
unknown,
Action
>;
export const wrapper = createWrapper<AppStore>(makeStore);
Обратите внимание на строку 22, где мы экспортируем специальную функцию wrapper
. Эта обертка устраняет необходимость в Provider
, который мы бы использовали в обычном React-приложении.
Обновление приложения
Нам осталось сделать еще одну вещь, чтобы завершить настройку нашей архитектуры Redux. Откройте файл _app.tsx
и оберните наш компонент следующим образом:
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { wrapper } from "../store/store";
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
export default wrapper.withRedux(MyApp);
Обратите внимание в строке 9, что мы оборачиваем наш компонент с помощью withRedux
. Мы можем обернуть и отдельные страницы, но это не рекомендуется; при переходе от одной страницы к другой, если эта страница не обернута, произойдет сбой.
Использование магазина Redux
Наша установка Redux завершена! Давайте используем наш магазин Redux внутри страницы index.tsx
следующим образом:
import type { NextPage } from "next";
import { selectAuthState, setAuthState } from "../store/authSlice";
import { useDispatch, useSelector } from "react-redux";
const Home: NextPage = () => {
const authState = useSelector(selectAuthState);
const dispatch = useDispatch();
return (
<div>
<div>{authState ? "Logged in" : "Not Logged In"}</div>
<button
onClick={() =>
authState
? dispatch(setAuthState(false))
: dispatch(setAuthState(true))
}
>
{authState ? "Logout" : "LogIn"}
</button>
</div>
);
};
export default Home;
Любое хранилище Redux имеет две основные цели: чтение и обновление.
В строке 6 видно, что мы читаем состояние, используя функцию useSelector
, предоставляемую react-redux
.
У нас есть кнопка, на которой мы можем переключить authState
, и на основе этого мы изменяем текст на кнопке.
Сохранение состояния в Next.js
Теперь мы успешно настроили наш магазин Redux. Вы можете проверить это, нажав на кнопку, которая будет отправлять действия, основанные на текущем состоянии, и обновлять хранилище, что в конечном итоге изменит состояние.
Но если вы обновите страницу, то увидите, что состояние не сохраняется. Это происходит потому, что в Next каждая страница рендерится по требованию, а значит, при переходе с одной страницы на другую предыдущее состояние исчезнет.
В данном случае, если пользователь вошел в систему, то при переходе на другую страницу он будет автоматически выходить из системы, так как начальное значение authState
определено как false.
Чтобы решить эту проблему, воспользуемся функцией-оберткой, которую мы создали ранее, и воспользуемся специальной функцией Next getServerSideProps
, так как она будет вызываться при каждой загрузке страницы.
Давайте добавим следующий код в наш файл index.tsx
:
export const getServerSideProps = wrapper.getServerSideProps(
(store) =>
async ({ params }) => {
// we can set the initial state from here
// we are setting to false but you can run your custom logic here
await store.dispatch(setAuthState(false));
console.log("State on server", store.getState());
return {
props: {
authState: false,
},
};
}
);
Здесь мы генерируем начальное состояние внутри функции getServerSideProps
, поэтому даже если вы обновите страницу, вы увидите, что значения состояния остаются неизменными.
Заключение
Вот как вы можете интегрировать Redux в приложение Next! Вы можете найти репозиторий GitHub для этого проекта здесь. Я также рекомендую вам ознакомиться с документацией next-redux-wrapper, чтобы узнать больше о других вариантах использования.
Хорошего дня!
LogRocket: Полная видимость производственных приложений Next.js
Отладка приложений Next может быть сложной задачей, особенно когда пользователи сталкиваются с проблемами, которые трудно воспроизвести. Если вы заинтересованы в мониторинге и отслеживании состояния Redux, автоматическом выявлении ошибок JavaScript, отслеживании медленных сетевых запросов и времени загрузки компонентов, попробуйте LogRocket.
LogRocket — это как видеорегистратор для веб- и мобильных приложений, записывающий буквально все, что происходит в вашем приложении Next. Вместо того чтобы гадать, почему возникают проблемы, вы можете собрать данные и отчитаться о том, в каком состоянии находилось ваше приложение в момент возникновения проблемы. LogRocket также отслеживает производительность вашего приложения, предоставляя такие показатели, как загрузка процессора клиента, использование памяти клиента и другие.
Пакет промежуточного ПО LogRocket Redux добавляет дополнительный уровень видимости пользовательских сессий. LogRocket регистрирует все действия и состояние ваших хранилищ Redux.
Модернизируйте отладку приложений Next.js — начните мониторинг бесплатно.