Что такое Zustand и как он используется
Что проверяют
Понимаете ли вы, как работает подписка на глобальное состояние и почему компонент перерисовывается. Сам Zustand маленький, поэтому разговор быстро уходит в селекторы, лишние рендеры и серверный рендеринг, где и ошибаются чаще всего.
Как отвечать
Zustand это библиотека состояния для React: стор создаётся функцией create, наружу отдаётся хук, оборачивать дерево провайдером не нужно. Данные и действия лежат в одном объекте, set принимает объект или функцию от текущего состояния.
import { create } from "zustand";
const useCounter = create<State>()((set) => ({
count: 0,
inc: () => set((s) => ({ count: s.count + 1 })),
}));
const count = useCounter((s) => s.count); // подписка только на это полеГлавное в ответе это селектор: хук без аргумента подписывает компонент на весь стор. Для выборки нескольких полей берут useShallow, иначе новый объект на каждом рендере сравнивается по ссылке и рендеры не прекращаются. Стоит упомянуть middleware (persist для localStorage, devtools, immer для вложенных структур), доступ вне React через getState и subscribe и привычку держать действия рядом с данными, а не раскидывать по компонентам.
Где спотыкаются
Достают состояние целиком, вида const { count, user } = useStore(). Компонент перерисовывается на любое изменение стора, включая поля, которых он не показывает, и обещанная производительность исчезает.
Создают стор на уровне модуля в приложении с серверным рендерингом. На сервере модуль один на все запросы, поэтому состояние одного пользователя протекает к другому, а с persist ещё и расходится разметка сервера и клиента. Лечится стором на запрос через провайдер и отложенной гидратацией.
Ждут от set глубокого слияния. Он объединяет только верхний уровень, вложенный объект приходится пересобирать целиком или подключать immer. Отсюда же тяга складывать в стор серверные данные и писать собственный кеш с инвалидацией вместо готового клиента запросов.