Если вы создаете даже небольшое веб-приложение, может случиться так, что вам потребуется хранить какие-то данные и передавать эти данные между компонентами и со страницы на страницу.
Обычно вы храните данные в состоянии. и вы управляете состоянием, обменивающимся между страницами и компонентами, используя контекст или платформу управления состоянием, например Redux. Такой подход может значительно усложнить ваше приложение, и это недостаток, особенно если вам нужно отслеживать простые вещи.

Что такое зустанд

Zustand — это легкое и простое в использовании решение для простого управления состояниями, оно простое в использовании и удовлетворит большинство потребностей, с которыми вы можете столкнуться при разработке веб-приложения, требующего управления состоянием. Кроме того, Zustand может сохранять данные между страницами и перезагружать их (подробнее об этом позже).



Работает ли Zusstand с Nextjs

Да! Zustand полностью совместим с Nextjs, но если вам нужно сохранить состояние, потребуются некоторые настройки, это связано с тем, как работает Nextjs, но с парой дополнительных строк все будет действительно гладко (в нашем примере мы сохраним состояние )

Когда Зустанд полезен?

Это зависит от вашего варианта использования, но учтите, что даже если Zustand легкий и простой, он очень мощный и имеет некоторые расширенные функции; поэтому каждый раз, когда вы начинаете с нуля, и состояние не очень сложное, вы можете попробовать Zustand. Если вам нужно отслеживать многоэтапную форму (например, опрос или сложную регистрацию), если вам нужно хранить некоторые данные о пользователе, если вам нужно отслеживать корзину (как в примере, который мы собираемся показать ). Кроме того, Zustand позволяет сохранять эти данные с помощью localStorage (или другого клиентского метода хранения), чтобы пользователь ничего не терял при перезагрузке или в других сеансах.

Как работает Зустанд?

На самом базовом уровне для работы с Zustand вы создаете Store, который представляет собой настраиваемый хук, чтобы его можно было реализовать везде в вашем приложении:

import create from 'zustand'
const useStore = create(set => ({
  bears: 0,
  increasePopulation: () => set(state => ({ bears: state.bears + 1 })),
}))

На странице или компоненте вы просто получаете доступ к хуку, так что вы можете получить доступ к состоянию и функциям, каждый раз, когда состояние обновляется, компонент перерисовывается:

function Home() {
  const bears = useStore(state => state.bears)
  const increasePopulation = useStore(state => state.increasePopulation)
   return {
      <h1>{bears}</h1>
      <button onClick={increasePopulation}>Add Bear</button>
   }
}

Что мы строим?

В этом примере мы воспользуемся Zustand для отслеживания пользовательской корзины на вымышленном веб-сайте электронной коммерции
Подробнее:

  • мы будем хранить всю корзину в состоянии: общая сумма корзины, количество товаров в корзине, список товаров в корзине
  • мы создадим некоторые функции состояния: добавление товара в корзину, обновление количества товара в корзине, удаление товара из корзины и очистка корзины.
  • мы будем хранить корзину в localStorage, чтобы пользователь не потерял свою корзину при просмотре страницы нашего сайта и даже если покинет сайт и вернется позже
  • мы внедрим на наших страницах необходимый код, чтобы сохранение состояния работало с Nextjs

Настройка проекта

Если вы хотите продолжить без написания кода, вы можете скачать репозиторий для этого проекта здесь:



Инициализируйте проект с помощью:

npx create-next-app state-mgt

Затем войдите во вновь созданную папку state-mgt и установите модуль Zustand:

npm install zustand

Мы также будем использовать Tailwind CSS для оформления нашего сайта, это совершенно необязательно, следуя официальной документации.



Затем мы очищаем проект, начиная с почти пустого файла index.js.

Настройка магазина

Первым делом определяем наш магазин в store/store.js

Это в основном определяет нашу ловушку (useCart), которая инициализируется с помощью метода create, хранилище (которое расширяется как persistone) будет содержать состояние состоит из total(число, представляющее общую стоимость корзины), totalqty(число с общим количеством товаров в корзине), cartContent (массив, содержащий товары в корзине, включая сведения о продукте, такие как количество, идентификатор, название и т. д.).
Затем мы определяем нашу функцию, которая будет обновляться (set ) штат:

  • addTocartдобавит товар в cartContent и увеличит total и totalqty.
  • updatecartто же самое, что и предыдущее, но вместо добавления новой строки в cartContent обновите количество существующей строки.
  • clearCartсброс состояния до исходного (пустого) значения
  • removeFromCartудалить строку из cartContent и обновить total и totalqty

Указанное имя в конце файла — это имя объекта в localStorage, здесь же можно указать способ хранения персистентности (подробнее в официальной документации)

Продукты

Для простоты и избегания настройки базы данных мы храним наши продукты в виде объектов в файле lib/products.js

Каждый продукт представляет собой объект с идентификатором, именем, ценой и деталями изображения (изображения хранятся в папке Nextjs public). Добавьте столько продуктов, сколько вам нужно/нравится.

Заголовок

В этом примере мы будем использовать общий заголовок, чтобы продемонстрировать использование состояния в компонентах и ​​сохранение состояния на разных страницах:

В заголовке всегда будет отображаться стоимость корзины и количество товаров в корзине. Как упоминалось ранее, поскольку мы работаем в Nextjs, способ отображения страниц (SSR и SSG) не позволяет напрямую обращаться к постоянному состоянию на клиенте, обходным путем является доступ к нему после монтирования компонента. В этом случае мы не получаем доступ и не отображаем total и totalqty, полученные от ловушки useCart, а отображаем mytotal и mytotalqty, которые являются двумя локальными состояниями, которые при изменении устанавливаются в состояние Zustand. В основном это связано с тем, что страницы рендерятся на сервере, и в процессе рендеринга они не могут получить доступ к клиентскому хранилищу для чтения значения; после того, как страница заполнена, осуществляется доступ к хранилищу клиента и извлекается значение; в этот момент значение клиента конфликтует со значением сервера, что приводит к предупреждению. Наличие этого «двойного рендеринга» решит проблему.

Еще один способ решить эту проблему в Nextjs — хранить состояние также удаленно (например, на Redis), чтобы при отрисовке сервера они не совпадали.

Страницы

Этот сайт будет иметь 3 страницы с общим заголовком: главная страница со списком продуктов, при нажатии на продукт он будет добавлен в корзину; страница корзины, которая покажет содержимое корзины и позволит удалить товар из корзины; о странице, которая является просто заполнителем.

Начнем с самого простого pages/about.js :

Эта страница не будет делать ничего, кроме заголовка

Главная страница будет pages/index.js:

На этой странице мы зацикливаем наши продукты и печатаем их в сетке, мы прикрепляем действие к каждому клику по продукту (addProduct(…)), чтобы каждый раз, когда продукт при нажатии сам товар добавляется (или обновляется) в корзину с помощью набора функций, присутствующих в хуке useCart

Страница корзины будет pages/cart.js:

Эта страница зацикливает продукты в корзине и показывает их, добавляя кнопку для их удаления из корзины. Как и в компоненте Header, нам нужно использовать локальные состояния, которые после гидратации заполняются состоянием Zusstand.

Если вы сейчас запустите проект:

npm run dev

и укажите в браузере:

http://localhost:3000

Вы должны получить наш вымышленный веб-сайт электронной коммерции, щелчок по продукту добавит его в корзину (и обновление состояния общего количества и количества обновит заголовок), перемещение между страницами не приведет к сбросу корзины (корзина сохраняется в localStarage) ; перейдя на страницу корзины, вы можете удалить товары (и, следовательно, обновить шапку).

Что дальше

Это всего лишь базовый пример того, как можно использовать Zustand для базового (и не очень) базового управления состоянием, конечно, это не полноценная электронная коммерция и управление состоянием не оптимизировано для производственной среды. В любом случае, это можно использовать в качестве отправной точки, особенно для разработчиков, которым необходимо интегрировать его в проект Nextjs.

Вы можете поддержать мою работу, купив мне кофе