@dhmk/zustand-lens

中文文档
5.0.0发布于 2024/10/24MITTypeScriptESM + CJS近 30 天下载 13.1万

月球支持 zustand

中文使用文档
文档目录22 节
  1. 安装
  2. 使用量
  3. API 密码
  4. withLenses(config: (set, get, api) => T): T
  5. withLenses(obj: T): T
  6. lens(fn: (set, get, api, context) => T): T
  7. createLens(set, get, path: string | string[]): [set, get]
  8. 字体
  9. 缩合
  10. 镜头中间软件
  11. 高级选项
  12. atomic(stateCreator)
  13. [meta]
  14. Understanding order of invocation.
  15. 杂项
  16. mergeDeep(a, b)
  17. mergeDeep(b)(a)
  18. mergeDeepLeft(a, b)
  19. persistOptions
  20. subscribe(store, selector, effect, options?)
  21. watch(selector, effect, options?)
  22. combineWatchers(...watchers)

@dhmk/zustand-lens (英语)

镜头支持 zu子。 。 。 .

通过这个软件包,您可以轻松地管理您主状态内的嵌入状态. 镜头允许您创建孤立和可再使用的组件.

一个镜头有一对功能 set 财务报告和审定财务报表 get 它们具有与zustand的功能相同的签名,但它们只在某个特定的主状态上运行.

简单比较一下:

import create from "zustand";
import { withLenses, lens } from "@dhmk/zustand-lens";

create(
  withLenses((set, get) => {
    // write and read whole state

    return {
      subStore: lens((subSet, subGet) => {
        // write and read `subStore` state
      }),
    };
  })
);

安装

npm install @dhmk/zustand-lens

使用量

import { create } from 'zustand'
import { withLenses, lens } from '@dhmk/zustand-lens'

// set, get - global
const useStore = create(withLenses((set, get, api) => {
  return {
    // set, get - only for storeA
    storeA: lens((set, get, api) => ({
      data: ...,

      action: (arg) => set({data: arg})
    })),

    // set, get - only for storeB
    storeB: lens((set, get, api) => ({
      data: ...,

      action: (arg) => set({data: arg})
    })),

    globalStore: {
      data: ...,

      action: () => set({...}) // global setter
    }
  }
}))

// or use a shorter version if you don't need global `set` and `get`
create(withLenses({
  storeA: lens(...),
  storeB: lens(...)
}))

API 密码

withLenses(config: (set, get, api) => T): T

withLenses(obj: T): T

中间软件功能.

它召唤 config 函数与默认 zustand 的参数相同 create 函数,然后转换返回的对象,以扩展全部 lens 实例到合适的对象.

也可以提供普通对象而不是函数.

lens(fn: (set, get, api, context) => T): T

创建透镜对象.

前两个参数 set 财务报告和审定财务报表 get 用于编写和读取全局状态子集的函数,相对于一个位置 lens 显示。 第三个, api 参数为zustand store 和最后一个参数 context 是一个镜头上下文.

type LensContext<T, S> = {
  set: Setter<T>; // `set` parameter
  get: Getter<T>; // `get` parameter
  api: ResolveStoreApi<S>; // `api` parameter
  rootPath: ReadonlyArray<string>; // path from root level of state
  relativePath: ReadonlyArray<string>; // path from parent lens or root
  atomic: (fn: () => void) => void; // see `atomic` middleware
};

斯特尔有这个签名: (value: Partial<T> | ((prev: T) => Partial<T>), replace?: boolean, ...args) => void。它将未知的参数传递给顶层 set 函数.

警告: 您不应该在代码中使用此函数的返回值。 它返回不透明对象,该对象通过 withLenses 函数.

页:1: 此函数用于在外部调用时抛出错误 withLenses 函数。 这是用来重音 lens 无法在之后动态创建 withLenses 已被调用。 但事先创建镜头是好的,所以我消除了这个错误(1.0.3和2.0.3). 现在你可以这样叫它:

const todosSlice = lens(() => ...)
const usersSlice = lens(() => ...)

const useStore = create(withLenses({
  todosSlice,
  usersSlice,
}))

另外,如果您想要将您的功能与 lens 包装 :

import { Lens, lens } from "@dhmk/zustand-lens";

/*
type Lens<
  T,      // slice type
  S,      // store state type or store api type
  Setter  // `set` function type
>
*/

type MenuState = {
  isOpened: boolean;

  toggle(open);
};

// `set` and `get` are typed
const menuState: Lens<MenuState> = (set, get, api) => ({
  isOpened: false,

  toggle(open) {
    set({ isOpened: open });
  },
});

const menuSlice = lens(menuState);

createLens(set, get, path: string | string[]): [set, get]

创建清晰的镜头对象.

这需要 set 财务报告和审定财务报表 get 参数和 path 返回一对设置器和获取器,该设置器和获取器运行在父状态的子集上,相对于 path你可以连锁镜头。 另外,您也可以将此函数作为独立函数使用,而不包含 withLenses 中间软件.

import { create } from "zustand";
import { createLens } from "@dhmk/zustand-lens";

const useStore = create((set, get) => {
  const lensA = createLens(set, get, "a");
  const lensB = createLens(...lensA, "b");
  const [setC] = createLens(...lensB, "c");

  return {
    a: {
      b: {
        c: {
          value: 111,
        },
      },
    },

    changeValue: (value) => setC({ value }),
  };
});

useStore.getState().changeValue(222);

console.log(useStore.getState());
/*
a: {
  b: {
    c: {
      value: 222
    }
  }
}
*/

字体

type Store = {
  id: number;
  name: string;

  nested: Nested;
};

type Nested = {
  text: string;
  isOk: boolean;

  toggle();
};

// option 1: type whole store
const store1 = create<Store>(
  withLenses({
    id: 123,
    name: "test",

    nested: lens((set) => ({
      text: "test",
      isOk: true,

      toggle() {
        set((p /* Nested */) => ({ isOk: !p.isOk }));
      },
    })),
  })
);

// option 2: type lens
const store2 = create(
  withLenses({
    id: 123,
    name: "test",

    nested: lens<Nested>((set) => ({
      text: "test",
      isOk: true,

      toggle() {
        set((p /* Nested */) => ({ isOk: !p.isOk }));
      },
    })),
  })
);

缩合

Immer被支持出柜. 然而,有一个告诫。 草稿的类型是 T 没有 Draft<T>。您可以自己添加,也可以不使用只读属性.

import { immer } from "zustand/middleware/immer";

const store = create<Store>()(
  immer(
    withLenses({
      id: 123,
      name: "test",

      nested: lens((set) => ({
        text: "test",
        isOk: true,

        toggle() {
          set((p /* Nested */) => {
            p.isOk = !p.isOk;
          });
        },
      })),
    })
  )
);

镜头中间软件

自兹 lens 取一个普通的功能,你可以用各种中件进行镜头对象的预处理,用zustand的同样方式进行.

此示例使用自定义 set 函数,它需要一个新的状态和记录的动作名称.

查看关于如何写作和打入中间软件的提示的源代码 .

import { lens, namedSetter } from "@dhmk/zustand-lens";

const test = lens(
  namedSetter((set) => ({
    name: "abc",

    setName() {
      set({ name: "def" }, "@test/setName");
    },
  }))
);

甚至可以创建自定义镜头.

import { lens, namedSetter } from "@dhmk/zustand-lens";

const lensWithNamedSetter = <T, S = unknown>(
  fn: Lens<T, S, NamedSet<T>>
): LensOpaqueType<T, S> => lens(namedSetter(fn));

高级选项

atomic(stateCreator)

原子集操作的中间软件. 原子操作可以有多个调用: setState 函数,但附加的回调 subscribe 函数只在原子块结尾处调用一次。 此中间软件启用 atomic 从镜头上下文的函数,并制作 [meta].setter 函数原子.

[meta]

高级镜头配置. 您可以将这个符号放入镜头或根态中. 如果您正在使用 Typescript 并想要将此符号添加到根状态, 您可能会遇到错误 。 在这种情况下,使用下列方法:

// add { [meta] } to your state type
create<State & { [meta] }>()(
  withLenses({
    // ...

    [meta]: {
      // ...
    },
  })
);

这个 [meta] 对象接受下列可选属性:

postprocess(state: T, prevState: T, ...args): Partial<T> | void

此函数在调用后调用 set 函数在将新状态合并到父状态之前 set 函数。 它被称作一个新的临时状态, 将被汇入,当前状态 和所有额外的论据, 被传递到一个 set 函数。 你可以回到新州,它会我与一个 state 参数。 此函数必须纯洁 。 你可以变异 state 参数仅在使用时 immer 中间软件.

setter(next: Function, context: LensContext): void

当调用镜头( 或 root) 时, 此函数会被调用 set 函数。 这样可以自定义预设和后设定的行为. 你可以在这里运行副作用。 你应该打电话 next 函数一次并同步将设置的操作委托给一个母镜(或root),类似于 next 函数在 express.js。如果您正在使用 atomic 中间软件,此函数将在原子上执行 。 也请使用 watch 帮助方便运行状态变化的副作用.

Understanding order of invocation.

鉴于以下商店:

const store = create(
  withLenses({
    someSlice: lens(() => ({
      nested: lens((set) => ({
        id: 1,
        test() {
          console.log("test before");
          set({ id: 2 });
          console.log("test after");
        },
        [meta]: {
          postprocess() {
            console.log("nested postprocess");
          },
          setter(set) {
            console.log("nested setter before");
            set();
            console.log("nested setter after");
          },
        },
      })),
      [meta]: {
        postprocess() {
          console.log("someSlice postprocess");
        },
        setter(set) {
          console.log("someSlice setter before");
          set();
          console.log("someSlice setter after");
        },
      },
    })),
    [meta]: {
      postprocess() {
        console.log("root postprocess");
      },
      setter(set) {
        console.log("root setter before");
        set();
        console.log("root setter after");
      },
    },
  })
);

store.getState().someSlice.nested.test();

控制台日志如下:

test before

nested setter before
someSlice setter before
root setter before

nested postprocess
someSlice postprocess
root postprocess

root setter after
someSlice setter after
nested setter after

test after

杂项

mergeDeep(a, b)

mergeDeep(b)(a)

合并对象 b 与 a 递归( 不合并数组) .

mergeDeepLeft(a, b)

合并对象 a 与 b (注释顺序). 有用吗 persist 中间软件.

persistOptions

帮助工具 persist 中间软件。 可以用不带镜头。 首先,你需要添加这些选项来坚持自己的配置. 现在您可以在您状态下的任何对象上附加选项,只需拨打 persistOptions 作为函数,并为对象提供两种可选函数: save 财务报告和审定财务报表 load每当你需要坚持状态, save 函数将被调用并持续返回值。 同样, load 函数将调用水合。 这使得您可以控制您想要保存/恢复哪些数据 。 两种功能必须纯洁,不要变换提供的论点.

const store = create(persist(() => ({
  // ... some state

  ...persistOptions({
    save(state) {
      // return an object that will be saved
    },

    load(persistedState) {
      // return an object that will be used as new state
    }
  })

  nested: {
    // ... some state

    // can be nested too
    ...persistOptions({
      save
      load
    })
  }
}), {
  name: 'my-store',
  // don't forget to add options to persist config
  ...persistOptions
}))

subscribe(store, selector, effect, options?)

备选案文 subscribeWithSelector 中间软件.

watch(selector, effect, options?)

类似 subscribe 函数,用于 setter 钩. 这叫镜头 set 函数先运行 effect 函数。 不需要退订.

combineWatchers(...watchers)

依次运行监视器(或任何类似设置的功能). 如果你有多个监视器,那就有用了。 示例

[meta]: {
  setter: combineWatchers(
    watch(state => state.id, handleIdChange),
    watch(state => state.name, handleNameChange)
  )
}

版本与发布记录

@dhmk/zustand-lens 共发布 27 个版本,首次发布于 2021/12/28;过去 12 个月发布了 0 个版本。

版本发布日期距今
5.0.0latest2024/10/242 年前
4.0.02024/02/272 年前
4.0.0-beta.4v42024/01/092 年前
4.0.0-beta.32024/01/052 年前
4.0.0-beta.22024/01/052 年前
4.0.0-beta.12024/01/012 年前

其他发布通道:getters → 1.0.0-getters,zustand3 → 1.0.5,v2 → 2.0.6,v4 → 4.0.0-beta.4。

关于 @dhmk/zustand-lens 的常见问题

@dhmk/zustand-lens 是什么?

月球支持 zustand

如何安装 @dhmk/zustand-lens?

在项目目录运行 npm install @dhmk/zustand-lens,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:zustand(^5.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@dhmk/zustand-lens 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dhmk/zustand-lens 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@dhmk/zustand-lens 可以商用吗?

@dhmk/zustand-lens 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dhmk/zustand-lens 的下载量有多少?

根据 npm 官方下载统计,@dhmk/zustand-lens 在 2026/10/12 – 2026/11/10 这 30 天内被下载 130,624 次,日均约 4,354 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dhmk/zustand-lens 还在维护吗?

最新版本 5.0.0 发布于 2024/10/24(2 年前);至今共发布 27 个版本,其中过去 12 个月发布了 0 个;首次发布于 2021/12/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。