Zustand Fetching Helpers
Introducing several functions that simplify working with zustand and clean up your store from unnecessary actions
and states.
The functions described below are well-typed and allow working with nested objects. Zustand suggests writing
custom slices and dividing the store into
several parts. However, in most cases, we need to divide the store into several parts because we add a lot of
unnecessary data, which can visually overload it.
I propose several helpers that will take on a significant portion of the typical data work in your store. First, it is
easier to see examples to understand
what it is and how it can help. In most cases, helpers will help lighten the store and there will be no need to split it
into several parts
Common view
const useStore = create<IState>(() => ({ ... }));
const useController = leiten[Controller](useStore, "dot.nested.path", [options]);
All actions and states out of your zustand
store. Live example
- leitenRequest
help you to handle request (any async function) and catch errors, return hook with params of request, and have
methods: action, clear, abort and set.
- leitenGroupRequest
handle a lot of similar requests dynamically, return hook with 2 overloads and have methods: call and clear.
- leitenRecord
working with objects, have methods set, patch and clear.
- leitenPrimitive
working with data like with primitive value, but it can be object, function or primitives. Have methods: set and _
clear_.
- leitenList
working with array, have methods: set, clear, add, update, remove, toggle and filter. If array item is
an
object then need to set compare function in the controller's options (third parameter).
- leitenNormalizedList
is the same as leitenList but working with normalized state.
- leitenModal
help to work with modals, have built in modal manager (if you want to open modal in cascade). Return hooks
with [openState, hiddenState], have methods: open, close and action.
All leitenControllers automatically calculate required type by path and throw typescript error if the specified
path does not satisfy the requirements of the controller or the established types.
Examples:
- Argument of type '"info.keywords.1"' is not assignable to parameter of type '"info.keywords"'.
- Argument of type 'string' is not assignable to parameter of type 'never'.
Library well tree shaking and have dependencies from immer, lodash-es and nanoid
Advanced
Options
leitenRecord, leitenPrimitive, leitenList and leitenNormalizedList have options with callbacks:
processingBeforeSet, sideEffect, patchEffect. You can use them to extend basic functionality
leitenRequest and leitenGrouprRequest have a useful reactions: fulfilled, rejected, abort, resolved
and action
Request
All requests working with useLeitenRequests. Usually you will never need it, but if you need it, then the record is
stored there with all the query parameters. The request key is returned by each leitenRequest
interface IState {
user: IUser | null;
}
const useExampleStore = create<IState>(() => ({
user: null,
}));
const useController = leitenRequest(useExampleStore, "user", getUser);
const User = () => {
const status = useLeitenRequests(state => state[useController.key].status)
return <>{status}</>
}
leitenMap also can be
helpful, example
Group Request
leitenGroupRequest return overloaded hook
interface IState {
cards: Record<string, ICard>;
}
const useExampleStore = create<IState>(() => ({
cards: {},
}));
export const useGroupController = leitenGroupRequest(
useExampleStore,
"cards",
async (props: ILeitenGroupRequestParams<string>) => {
return getCard(props.params);
},
);
const status = useGroupController(id, (state) => state.status);
or
const requests = useGroupController((state) => state);
Store
Wrappers for ContextStore
and ResettableStore
Slices
Here are examples of our helpers
for slices