Socket
Socket
Sign inDemoInstall

zustand-fetching

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zustand-fetching - npm Package Compare versions

Comparing version 2.3.4 to 2.4.1

1

dist/examples/controllers/6_Controller_GroupRequest.js

@@ -8,2 +8,3 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";

cards: {},
array: [],
}));

@@ -10,0 +11,0 @@ export const useGroupController = leitenGroupRequest(useExampleStore, "cards", async (props) => {

5

dist/helpers/leitenGroupRequest.d.ts

@@ -24,3 +24,6 @@ import { StoreApi } from "zustand/esm";

}
export declare const leitenGroupRequest: <Store extends object, P extends DotNestedKeys<Store>, Payload, Result>(store: StoreApi<Store>, path: P extends string ? DotNestedValue<Store, P> extends Record<string, Result> | null ? P : never : never, payloadCreator: (params: ILeitenGroupRequestParams<Payload>) => Promise<Result>, options?: ILeitenGroupRequestOption<Payload, Result> | undefined) => ILeitenGroupRequest<Payload, Result>;
interface ILeitenGroupRequestArrayOption<Payload, Result> extends ILeitenGroupRequestOption<Payload, Result> {
getKey: (value: Result) => string;
}
export declare const leitenGroupRequest: <Store extends object, P extends DotNestedKeys<Store>, Payload, Result>(store: StoreApi<Store>, path: P extends string ? DotNestedValue<Store, P> extends Record<string, Result> | Result[] ? P : never : never, payloadCreator: (params: ILeitenGroupRequestParams<Payload>) => Promise<Result>, options?: (DotNestedValue<Store, P> extends Record<string, Result> ? ILeitenGroupRequestOption<Payload, Result> : ILeitenGroupRequestArrayOption<Payload, Result>) | undefined) => ILeitenGroupRequest<Payload, Result>;
export {};
import { produce } from "immer";
import { set } from "lodash-es";
import { get, set } from "lodash-es";
import { shallow } from "zustand/shallow";

@@ -10,6 +10,36 @@ import { useLeitenRequests } from "../hooks/useLeitenRequest";

let requests = {};
const isArray = Array.isArray(get(store.getState(), path));
const getPathToArrayItem = (key) => {
const source = get(store.getState(), path, []);
const find = source.findIndex((s) => {
var _a;
return ((_a = options === null || options === void 0 ? void 0 : options.getKey) === null || _a === void 0 ? void 0 : _a.call(options, s)) === key;
});
const index = find !== -1 ? find : source.length;
const withKey = (path + `["${index}"]`);
return { withKey, isNew: find === -1 };
};
const add = (key) => {
const state = requests[key];
if (!state) {
const pathWithKey = (path + `.["${key}"]`);
// const state = requests[key];
// if (!state) {
let pathWithKey = "";
let payload = payloadCreator;
if (isArray) {
const before = getPathToArrayItem(key);
pathWithKey = before.withKey;
// eslint-disable-next-line
// @ts-ignore
payload = async (params) => {
const result = await payloadCreator(params);
const after = getPathToArrayItem(key);
if ((before.isNew && after.isNew) || !after.isNew) {
const nextState = produce(store.getState(), (draft) => {
set(draft, after.withKey, result);
});
store.setState(nextState);
}
};
}
else {
pathWithKey = (path + `.${key}`);
const nextState = produce(store.getState(), (draft) => {

@@ -20,7 +50,5 @@ var _a;

store.setState(nextState);
requests[key] = leitenRequest(store, pathWithKey, payloadCreator, options);
}
else {
requests[key].clear();
}
requests[key] = leitenRequest(store, pathWithKey, payload, options);
// }
};

@@ -31,3 +59,3 @@ const call = (params, options) => {

const payload = { key, params };
if (request) {
if (request && !isArray) {
request.action(payload, options);

@@ -43,3 +71,3 @@ }

if (key) {
requests[key].clear();
!isArray && requests[key].clear();
delete requests[key];

@@ -46,0 +74,0 @@ }

{
"name": "zustand-fetching",
"version": "2.3.4",
"version": "2.4.1",
"private": false,
"description": "Zustand fetching helpers",
"description": "Zustand state manager controllers",
"repository": {

@@ -95,3 +95,3 @@ "type": "git",

"publishConfig": {
"homepage": "https://github.com/Hecmatyar/zustand-fetching"
"homepage": "https://github.com/Hecmatyar/zustand-fecthing"
},

@@ -104,4 +104,6 @@ "license": "MIT",

"store",
"helpers"
"helpers",
"constrollers",
"lenses"
]
}

@@ -1,17 +0,28 @@

# Zustand Fetching Helpers
# Zustand controllers
> Introducing several functions that simplify working with **zustand** and clean up your store from unnecessary actions
> and states.
> Helps to avoid using other state managers to execute requests and allows you to work efficiently with zustand.
The functions described below are _**well-typed**_ and allow working with _**nested**_ objects. Zustand suggests writing
custom [slices](https://github.com/pmndrs/zustand/blob/main/docs/guides/slices-pattern.md) 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.
The Zustand Fetching Helpers library provides a set of functions and controllers that facilitate working with Zustand, a
state management library. The functions described below are _**well-typed**_ and allow working with _**nested**_
objects. While Zustand suggests writing
custom [slices](https://github.com/pmndrs/zustand/blob/main/docs/guides/slices-pattern.md) to divide the store into
several parts, this library aims to simplify common data-related tasks without the need for additional state management
solutions.
I propose several helpers that will take on a significant portion of the typical data work in your store. First of all,
it is easier to see
[Live example on codesandbox](https://codesandbox.io/p/sandbox/bitter-lake-w57ywe?selection=%5B%7B%22endColumn%22%3A44%2C%22endLineNumber%22%3A49%2C%22startColumn%22%3A44%2C%22startLineNumber%22%3A49%7D%5D&file=%2Fsrc%2Frequest%2FRequest.tsx)
to understand what it is and how it works. In most cases, leiten controllers will help lighten the
store and there will be no need to split it into several parts.
To get a better understanding of what this library offers and how it works, you can refer to
the [live example on CodeSandbox](https://codesandbox.io/p/sandbox/bitter-lake-w57ywe?selection=%5B%7B%22endColumn%22%3A44%2C%22endLineNumber%22%3A49%2C%22startColumn%22%3A44%2C%22startLineNumber%22%3A49%7D%5D&file=%2Fsrc%2Frequest%2FRequest.tsx)
. In many cases, the provided controllers will help reduce the complexity of your store, eliminating the need to split
it into multiple parts.
## Installation
You can install the library using npm:
```bash
npm install leiten-zustand
```
Since "Zustand" translates to "state" in German, we decided to adhere to the same naming strategy and used the word "
leiten" (meaning "lead" and "manage") to denote our controllers.
Common view

@@ -24,31 +35,86 @@

All actions and states out of your **zustand**
### Small Example
Let's create some fake example: load some data and then change it.
#### Pure zustand
```tsx
const useStore = create<IStore>((set, get) => ({
loadData: async (id: string) => {
try {
set({ loadingData: true })
const response = await getData(id);
set({ data: response })
} catch {
// Todo show error
} finally {
set({ loadingData: false })
}
},
loadingData: false,
data: { user: null, cards: [] },
updateUser: (user: Partial<IUser>) => {
set({ data: { ...get().data, user: { ...get().data?.user, ...user } } })
},
removeCard: (cardId: string) => {
const cards = get().data.cards.filter(card => card.id !== cardId);
set({ data: { ...get().data, cards } })
}
}))
```
#### With leiten controllers
```tsx
const useStore = create<IStore>(() => ({
data: { user: null, cards: [] },
}));
// loadData & loadingData
const useRequest = leitenRequest(useStore, "data", (id: string) => getData(id));
// updateUser
const userController = leitenRecord(useStore, "data.user");
// removeCard
const cardsController = leitenList(useStore, "data.cards", { compare: (a, b) => a.id == b.id });
```
Using "leiten" controllers empowers you to simplify your state management by removing redundant actions, eliminating
unnecessary states, and reducing the complexity of working with nested objects. By adopting "leiten" controllers you can
create a cleaner and more streamlined store structure, making it easier to manage and manipulate your application's
data.
All actions and states for your **zustand**
store. [Examples](https://github.com/Hecmatyar/zustand-fetching/tree/main/src/examples/controllers)
- [leitenRequest](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/1_Controller_Request.tsx)
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_.
Helps handle requests (any async function) and catch errors. Returns a **hook** with request parameters and provides
methods such as _action_, _clear_, _abort_, and _set_.
- [leitenGroupRequest](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/6_Controller_GroupRequest.tsx)
handle a lot of similar requests dynamically, return **hook** with 2 overloads and have methods: _call_ and _clear_.
Handles multiple similar requests dynamically. Returns a **hook** with two overloads and provides methods such
as _call_ and _clear_. Can work with arrays as well as with the normalized list.
- [leitenRecord](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/2_Controller_Record.tsx)
working with objects, have methods _set_, _patch_ and _clear_.
Works with objects and provides methods such as _set_, _patch_ and _clear_.
- [leitenPrimitive](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/3_Controller_Primitive.tsx)
working with data like with primitive value, but it can be object, function or primitives.
Have methods: _set_ and _clear_.
Works with data as if it were a primitive value, but it can be an object, function, or primitives. Provides methods
such as _set_ and _clear_.
- [leitenList](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/4_Controller_List.tsx)
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).
Works with arrays and provides methods such as _set_, _clear_, _add_, _update_, _remove_, _toggle_, and _filter_. If
the array item
is an object, a **compare** function needs to be set in the controller's options (third parameter).
- [leitenNormalizedList](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/4_Controller_List.tsx)
is the same as leitenList but working with normalized state.
Same as leitenList but works with normalized state.
- [leitenModal](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/5_Controller_Modal.tsx)
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_.
Helps work with modals and provides a built-in modal manager for cascading modals. Returns hooks
with [openState, hiddenState] and provides methods such as _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:
> All leitenControllers automatically infer the required types based on the specified path and will throw a **TypeScript
> error** if the provided path does not match the controller's requirements or 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'.
⚠️ If you encounter an error when specifying the path to your field in the store, it is likely because you are
attempting to attach a controller to a field with an incompatible type. Please ensure that the field you are attaching
the controller to has a permitted type to resolve this issue.
Library well tree shaking and have dependencies from **immer**, **lodash-es** and **nanoid**

@@ -60,8 +126,45 @@

**leitenRecord**, **leitenPrimitive**, **leitenList** and **leitenNormalizedList** have options with callbacks: _
sideEffect_ and _patchEffect_. You can use them to extend basic functionality
**leitenRecord**, **leitenPrimitive**, **leitenList** and **leitenNormalizedList** have options with callbacks:
_sideEffect_ and _patchEffect_. You can use them to extend basic functionality
**leitenRequest** and **leitenGrouprRequest** have a useful reactions: _fulfilled_, _rejected_, _abort_, _resolved_
```tsx
const useExampleStore = create<IState>(() => ({ user: null }));
const recordController = leitenRecord(useExampleStore, "user", {
sideEffect: (value: { prev: IUser; next: IUser }) => {
// you can execude here some side actions
},
patchEffect: (value: VALUE) => {
// you can update your entire store here in one tick with value update
},
});
```
**leitenRequest** and **leitenGroupRequest** have a useful reactions: _fulfilled_, _rejected_, _abort_, _resolved_
and _action_
```tsx
const useExampleStore = create<IState>(() => ({ user: null }));
const recordController = leitenRequest(useExampleStore, "user", async (id: string) => getUser(id), {
fulfilled: ({ previousResult, result, payload }) => {
// do something after successful request
},
rejected: ({ previousResult, error, payload }) => {
// do something after error request
},
abort: ({ previousResult, payload }) => {
// do something after request was aborted
},
resolved: ({ previousResult, payload }) => {
// do something after request was resolved
},
action: ({ previousResult, payload }) => {
// do something before request was called
},
optimisticUpdate: (payload) => {
//if you use this callback, then leitenRequest will automatically switch to optimistic update mode
},
initialStatus: ILoadingStatus // initial status if request, init by default
});
```
- leitenList - if you are using object then you also should specify **compare** function like in example

@@ -87,3 +190,4 @@ - leitenNormalizedList - in addition to the **compare** function, you also need to define the **getKey** function

const User = () => {
const status = useController(state => state[useController.key].status)
// const status = useController(state => state.status) - the same
const status = useLeitenRequests(state => state[useController.key].status)
return <>{status}</>

@@ -93,7 +197,28 @@ }

leitenMap also can be
helpful, [example](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/6_Controller_GroupRequest.tsx)
leitenMap also can be helpful,
[example](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/controllers/6_Controller_GroupRequest.tsx)
### Group Request
leitenGroupRequest works equally well with both a normalized list and a regular array. If you are using an array, make
sure to specify the **getKey** function, as shown in the example
below. [Codesandbox link](https://codesandbox.io/p/sandbox/cool-night-0mo1l7?file=%2Fsrc%2Frequest%2FRequest.tsx) with
arrays
```tsx
interface IStore {
record: Record<string, ICard>,
array: ICard[],
}
const useStore = create<IStore>(() => ({
record: {},
array: []
}));
const useRecordController = leitenGroupRequest(useStore, "record", (id: string) => getCard(id))
const useArrayController = leitenGroupRequest(useStore, "array", (id: string) => getCard(id), {
getKey: (value) => value.id
})
```
leitenGroupRequest return overloaded hook

@@ -124,3 +249,5 @@

Wrappers for [ContextStore](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/store/ContextStore.tsx)
and [ResettableStore](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/store/ResettableStore.tsx)
The library provides wrappers
for [ContextStore](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/store/ContextStore.tsx)
and [ResettableStore](https://github.com/Hecmatyar/zustand-fetching/blob/main/src/examples/store/ResettableStore.tsx).
These wrappers can be used to enhance your Zustand store with additional features.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc