Отслеживание изменений состояния с помощью плагина Zustand

Отслеживание изменений состояния с помощью плагина Zustand

Отслеживание изменений состояния с помощью плагина Zustand

Zustand — это очень быстрая и минималистичная замена решениям для управления состоянием, таким как Redux. С помощью нашего плагина Zustand вы можете отслеживать изменения состояния на протяжении всего жизненного цикла вашего приложения.

Установка плагина

Section titled Установка плагина

Плагин можно легко установить с помощью следующей команды:

npm i @openreplay/tracker-zustand

Использование плагина в приложении Next.js

Section titled Использование плагина в приложении Next.js

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

Провайдер Context, который я использую, позволяет настраивать Tracker Plugins, поэтому после установки плагина мы изменим файл _app.tsx, добавив приведённую ниже инструкцию импорта:

import trackerZustand from '@openreplay/tracker-zustand'

А затем основная функция App должна выглядеть так:

export default function MyApp({ Component, pageProps }: AppProps) {
  const Layout = (Component as any).Layout || Noop

  useEffect(() => {
    document.body.classList?.remove('loading')
  }, [])

  let plugins = [
    {
      fn: trackerZustand,
      name: 'zustand',
    },
  ]

  return (
    <TrackerProvider
      config={{
        plugins
      }}
    >
      <Head />
      <ManagedUIContext>
        <Layout pageProps={pageProps}>
          <Component {...pageProps} />
        </Layout>
      </ManagedUIContext>
    </TrackerProvider>
  )
}

Это автоматически инициализирует плагин вместе с трекером, а также сделает доступными данные, возвращаемые при выполнении основной функции плагина.

Следующий шаг — создать store; через минуту мы будем добавлять в этот store товары с сайта электронной коммерции.

Создание store с помощью плагина Zustand

Section titled Создание store с помощью плагина Zustand

Использование плагина требует изменить способ, которым вы обычно создаёте экземпляр store Zustand, поэтому смело копируйте и вставляйте следующий код в качестве шаблона:

import create from 'zustand'

const productStore = null
export const useProductsStore = (logger) => {
  if (!productStore) {
    //use a singleton pattern to make sure we only create the store the first time around
    productStore = createProductStore(logger)
  }
  return productStore
}

function createProductStore(logger) {
  return create(
    logger((set) => ({
      products: [],
      addProduct: (p) =>
        set((state) => {
          const prodFound = state.products.find((prod) => {
            return p.id == prod.id
          })
          if (prodFound) {
            p.amount = prodFound.amount + 1
          } else {
            p.amount = 1
          }

          return {
            products: [...state.products.filter((prod) => p.id != prod.id), p],
          }
        }),
    }))
  )
}

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

С другой стороны, функция createProductStore создаст store, задаст логику для метода addProduct и использует функцию logger, которую мы ей передаём. Этот logger, как вы, вероятно, уже догадались, — тот самый, который мы получили при использовании плагина Zustand.

Когда store готов, мы можем начать добавлять в него товары.

Добавление товаров в наш store

Section titled Добавление товаров в наш store

Store экспортирует метод addProduct, который отвечает за отслеживание товаров в нашей корзине.

Чтобы импортировать функцию в свой код, вам нужно:

  1. Импортировать и использовать провайдер контекста Tracker.
  2. Получить атрибут pluginsReturnedValue из контекста.
  3. Использовать его для вызова метода zustand (обратите внимание, что метод назван по значению атрибута name, заданному при настройке плагина выше), и передать строковый атрибут, чтобы дать store имя (это имя будет использоваться во время воспроизведения).
  4. Метод zustand вернёт logger, который мы будем использовать при вызове хука useProductStore из zustand (того, что мы создали для store).

Всё это кажется слишком сложным, но по сути всё сводится к следующему:

const { pluginsReturnedValues } = useContext(TrackerContext)

const useProductStoreTracked = useProductsStore(
  pluginsReturnedValues.zustand('products_store')
)
const { addProduct } = useProductStoreTracked()

Теперь вы можете просто вызвать метод addProduct, и он добавит товары из корзины в store.

Чтение данных из store

Section titled Чтение данных из store

Как вы, вероятно, догадываетесь, если вы хотите прочитать данные из store Zustand, вам нужно выполнить тот же набор шагов. Но вместо того чтобы брать метод addProduct, мы деструктурируем массив products.

Вот так:

const { pluginsReturnedValues } = useContext(TrackerContext)

const useProductStoreTracked = useProductsStore(
  pluginsReturnedValues.zustand('products_store')
)
const { products } = useProductStoreTracked()

Затем вы можете обычным образом перебирать товары:

<div>
  {products.map((p: Product, idx: Number) => {
    return (
      <div key={+idx}>
        {p.name}({p.amount})
      </div>
    )
  })}
</div>

Приведённый выше код перебирает список товаров и отображает их на экране. Каждый раз, когда вы добавляете в store ещё один товар, он также будет обновляться здесь.

Синхронизация состояния с session replay

Section titled Синхронизация состояния с session replay

Чтобы просмотреть изменения состояния во время воспроизведения, просто нажмите на новую вкладку Zustand в правом нижнем углу:

New tab for the Zustand tracked data

При нажатии на неё вы увидите содержимое store и сможете понять, как оно меняется, а также какие данные в нём сохраняются:

State data shown during the replay

Обратите внимание на имя store: это на самом деле то имя, которое мы использовали при первом вызове метода zustand.

Если вы используете не Next.js, а другой фреймворк, способ использования должен быть похожим; ключевым является то, как вы создаёте store. Пока вы находите способ использовать функцию logger при его создании, вы сможете отслеживать состояние во время воспроизведения.

Вы можете ознакомиться с этим репозиторием, чтобы увидеть полный исходный код рабочего приложения Next.js с плагином Zustand.

Если у вас возникнут какие-либо проблемы с настройкой плагина Zustand в вашем проекте, свяжитесь с нами в нашем сообществе Slack и задайте вопросы напрямую нашим разработчикам!