Перейти к содержанию

Автоматическая генерация селекторов

Мы рекомендуем использовать селекторы при использовании свойств или действий из хранилища. Вы можете получить доступ к значениям из хранилища следующим образом:

1
const bears = useBearStore((state) => state.bears);

Однако их написание может быть утомительным. Если это так, вы можете автоматически генерировать селекторы.

создайте следующую функцию: createSelectors

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { StoreApi, UseBoundStore } from 'zustand';

type WithSelectors<S> = S extends {
    getState: () => infer T;
}
    ? S & { use: { [K in keyof T]: () => T[K] } }
    : never;

const createSelectors = <
    S extends UseBoundStore<StoreApi<object>>
>(
    _store: S
) => {
    let store = _store as WithSelectors<typeof _store>;
    store.use = {};
    for (let k of Object.keys(store.getState())) {
        (store.use as any)[k] = () =>
            store((s) => s[k as keyof typeof s]);
    }

    return store;
};

Если у вас есть такое хранилище:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
interface BearState {
    bears: number;
    increase: (by: number) => void;
    increment: () => void;
}

const useBearStoreBase = create<BearState>()((set) => ({
    bears: 0,
    increase: (by) =>
        set((state) => ({ bears: state.bears + by })),
    increment: () =>
        set((state) => ({ bears: state.bears + 1 })),
}));

Примените эту функцию к своему хранилищу:

1
const useBearStore = createSelectors(useBearStoreBase);

Теперь селекторы генерируются автоматически, и вы можете обращаться к ним напрямую:

1
2
3
4
5
// get the property
const bears = useBearStore.use.bears();

// get the action
const increment = useBearStore.use.increment();

Ванильное хранилище

Если вы используете ванильное хранилище, воспользуйтесь следующей функцией createSelectors:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import { StoreApi, useStore } from 'zustand';

type WithSelectors<S> = S extends {
    getState: () => infer T;
}
    ? S & { use: { [K in keyof T]: () => T[K] } }
    : never;

const createSelectors = <S extends StoreApi<object>>(
    _store: S
) => {
    const store = _store as WithSelectors<typeof _store>;
    store.use = {};
    for (const k of Object.keys(store.getState())) {
        (store.use as any)[k] = () =>
            useStore(_store, (s) => s[k as keyof typeof s]);
    }

    return store;
};

Использование такое же, как и в хранилище React. Если у вас есть такое хранилище:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import { createStore } from 'zustand';

interface BearState {
    bears: number;
    increase: (by: number) => void;
    increment: () => void;
}

const store = createStore<BearState>((set) => ({
    bears: 0,
    increase: (by) =>
        set((state) => ({ bears: state.bears + by })),
    increment: () =>
        set((state) => ({ bears: state.bears + 1 })),
}));

Примените эту функцию к своему хранилищу:

1
const useBearStore = createSelectors(store);

Теперь селекторы генерируются автоматически, и вы можете обращаться к ним напрямую:

1
2
3
4
5
// get the property
const bears = useBearStore.use.bears();

// get the action
const increment = useBearStore.use.increment();

Живая демонстрация

Рабочий пример этого можно найти в Code Sandbox.

Библиотеки сторонних разработчиков

Источник — https://docs.pmnd.rs/zustand/guides/auto-generating-selectors

Комментарии