Към всички skills

react-zustand-patterns

aiskillstore · Разработка

Zustand state management patterns for React. Use when working with Zustand stores, debugging state timing issues, or implementing async actions. Works for both React web and React Native.

Оригинален текст · няма потвърден превод на български

Първо прочетете инструкцията.

Файлът се зарежда от посочения източник само по ваше действие. Можете да го прочетете тук, да го копирате или да го запазите като .md.

Оригинален SKILL.md
GitHub хранилище
Звезди на репото
428
Лиценз
Не е посочен. Проверете в репозитория.
Последна проверка на записа
Няма посочена дата

Добавете в своя инструмент.

Командата отваря избора на skills от репозитория. Прочетете файла и условията на автора преди изпълнение.

npx skills add aiskillstore/marketplace

Страницата копира текст. Не инсталира и не изпълнява нищо на устройството ви.

Откъс от SKILL.md

Началото на файла на автора, без превод.

Zustand Patterns for React

Problem Statement

Zustand's simplicity hides important timing details. set() is synchronous, but React re-renders are batched. getState() escapes stale closures. Async actions in stores need careful handling. Understanding these internals prevents subtle bugs.


Pattern: set() is Synchronous, Renders are Batched

Problem: Assuming state is "ready" for React immediately after set().

const useStore = create((set, get) => ({
  count: 0,

  increment: () => {
    set({ count: get().count + 1 });
    // State IS updated here (set is sync)
    console.log(get().count); // ✅ Shows new value

    // But React hasn't re-rendered yet
    // Component will see old value until next render cycle
  },
}));

Key insight:

  • set() updates the store synchronously
  • getState() immediately reflects the new value
  • React components re-render asynchronously (batched)

When this matters:

  • Chaining multiple state updates
  • Validating state after update
  • Debugging "stale" component values

Pattern: getState() Escapes Stale Closures

Problem: Callbacks and async functions capture state at creation time. Using get() or getState() always gets current state.

const useStore = create((set, get) => ({
  data: {},

  // WRONG - closure captures stale state
  saveDataBad: (id: string, value: number) => {
    setTimeout(() => {
      // If someone passed `data` as a parameter, it would be stale
    }, 1000);
  },

  // CORRECT - always use get() for current state
  saveData: async (id: string, value: number) => {
    await someAsyncOperation();
    // After await, use get() to ensure current state
    const currentData = get().data;
    set({ data: { ...currentData, [id]: value } });
  },
}));

// In components - same principle
function Component() {
  const data = useStore((s) => s.data);

  const handleSave = async () => {
    await delay(1000);
    // data here is stale! Captured at render time

    // Use getState() for current value
    const current = useStore.getState().data;
  };
}

Rule: After any await, use get() or getState() - never rely on closure-captured values.


Pattern: Async Actions in Stores

Problem: Async actions need explicit async/await and careful state reads after awaits.

Целият SKILL.md в GitHub