zustand-computed 中文文档教程

发布于 2年前 浏览 22 项目主页 更新于 2年前

zustand-compulated

“npm构建状态下载< /a> Issues

zustand-compulated 是一个轻量级、TypeScript 友好的状态管理系统中间件 Zustand 。这是一个简单的层,在商店中发生任何状态更改后添加转换函数。

安装

yarn add zustand-computed

用法

中间件层接受您的存储创建函数和计算函数,该函数将您的状态转换为计算状态。它不需要处理合并状态。

import computed from "zustand-computed"

const computeState = (state) => ({
  countSq: state.count ** 2,
})

const useStore = create(
  computed(
    (set) => ({
      count: 1,
      inc: () => set((state) => ({ count: state.count + 1 })),
      dec: () => set((state) => ({ count: state.count - 1 })),
    }),
    computeState
  )
)

对于类型,前面的示例将如下所示:

import computed from "zustand-computed"

type Store = {
  count: number
  inc: () => void
  dec: () => void
}

type ComputedStore = {
  countSq: number
}

const computeState = (state: Store): ComputedStore => ({
  countSq: state.count ** 2,
})

// use curried create
const useStore = create<Store>()(
  computed(
    (set) => ({
      count: 1,
      inc: () => set((state) => ({ count: state.count + 1 })),
      dec: () => set((state) => ({ count: state.count - 1 })),
    }),
    computeState
  )
)

然后可以在 React 组件中或通过 Zustand API 正常使用存储。

function Counter() {
  const { count, countSq, inc, dec } = useStore()
  return (
    <div>
      <span>{count}</span>
      <br />
      <span>{countSq}</span>
      <br />
      <button onClick={inc}>+1</button>
      <button onClick={dec}>-1</button>
    </div>
  )
}

可以在“example”目录下找到功能齐全的示例。

使用中间件

这是一个使用中间件的示例。按预期工作。

const useStore = create<Store>()(
  devtools(
    computed(
      immer((set) => ({
        count: 1,
        inc: () =>
          set((state) => {
            // example with Immer middleware
            state.count += 1
          }),
        dec: () => set((state) => ({ count: state.count - 1 })),
      })),
      computeState
    )
  )
)

选择器

默认情况下,当 zustand-compulated 运行 computeState 函数时,它会跟踪访问的变量,并且如果这些变量之一没有更改,则不会触发计算。如果您在computeState内部嵌套了控制流,或者您希望它在所有更改上运行,而不管在computeState内部使用,这可能会出现问题代码>.要禁用自动选择器检测,您可以将第三个 opts 变量传递给 compated 构造函数,例如

const useStore = create<Store, [["chrisvander/zustand-computed", ComputedStore]]>(
  computed(
    (set) => ({
      count: 1,
      inc: () => set((state) => ({ count: state.count + 1 })),
      dec: () => set((state) => ({ count: state.count - 1 })),
    }),
    computeState,
    { disableProxy: true }
  )
)

其他选项包括传递 keys 数组,该数组明确拼写出触发重新计算的选择器。您还可以传递自定义 equalityFn,例如 fast-deep-equal 而不是默认的 zustand/shallow 。

zustand-computed

npm packageBuild StatusDownloadsIssues

zustand-computed is a lightweight, TypeScript-friendly middleware for the state management system Zustand. It's a simple layer which adds a transformation function after any state change in your store.

Install

yarn add zustand-computed

Usage

The middleware layer takes in your store creation function and a compute function, which transforms your state into a computed state. It does not need to handle merging states.

import computed from "zustand-computed"

const computeState = (state) => ({
  countSq: state.count ** 2,
})

const useStore = create(
  computed(
    (set) => ({
      count: 1,
      inc: () => set((state) => ({ count: state.count + 1 })),
      dec: () => set((state) => ({ count: state.count - 1 })),
    }),
    computeState
  )
)

With types, the previous example would look like this:

import computed from "zustand-computed"

type Store = {
  count: number
  inc: () => void
  dec: () => void
}

type ComputedStore = {
  countSq: number
}

const computeState = (state: Store): ComputedStore => ({
  countSq: state.count ** 2,
})

// use curried create
const useStore = create<Store>()(
  computed(
    (set) => ({
      count: 1,
      inc: () => set((state) => ({ count: state.count + 1 })),
      dec: () => set((state) => ({ count: state.count - 1 })),
    }),
    computeState
  )
)

The store can then be used as normal in a React component or via the Zustand API.

function Counter() {
  const { count, countSq, inc, dec } = useStore()
  return (
    <div>
      <span>{count}</span>
      <br />
      <span>{countSq}</span>
      <br />
      <button onClick={inc}>+1</button>
      <button onClick={dec}>-1</button>
    </div>
  )
}

A fully-featured example can be found under the "example" directory.

With Middleware

Here's an example with middleware. Works as expected.

const useStore = create<Store>()(
  devtools(
    computed(
      immer((set) => ({
        count: 1,
        inc: () =>
          set((state) => {
            // example with Immer middleware
            state.count += 1
          }),
        dec: () => set((state) => ({ count: state.count - 1 })),
      })),
      computeState
    )
  )
)

Selectors

By default, when zustand-computed runs your computeState function, it tracks accessed variables and does not trigger a computation if one of those variables do not change. This could potentially be problematic if you have nested control flow inside of computeState, or perhaps you want it to run on all changes regardless of use inside of computeState. To disable automatic selector detection, you can pass a third opts variable to the computed constructor, e.g.

const useStore = create<Store, [["chrisvander/zustand-computed", ComputedStore]]>(
  computed(
    (set) => ({
      count: 1,
      inc: () => set((state) => ({ count: state.count + 1 })),
      dec: () => set((state) => ({ count: state.count - 1 })),
    }),
    computeState,
    { disableProxy: true }
  )
)

Other options include passing a keys array, which explicitly spell out the selectors which trigger re-computation. You can also pass a custom equalityFn, such as fast-deep-equal instead of the default zustand/shallow.

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文