如何在 React 中进行状态管理?使用 Zustand!

计数器

tsx
import { create } from 'zustand'

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

function Controls() {
  const inc = useStore(state => state.inc)
  return <button onClick={inc}>one up</button>
}

function Counter() {
  const count = useStore(state => state.count)
  return <h1>{count}</h1>  
}

用法

创建状态 state 操作 action

Basic typescript usage doesn’t require anything special except for writing create<State>()(...) instead of create(...)

tsx
import { create } from 'zustand'

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

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

const useFishStore = create((set) => ({
  salmon: 1,
  tuna: 2,
  deleteEverything: () => set({}, true), // clears the entire store, actions included
  deleteTuna: () => set((state) => omit(state, ['tuna']), true),
}))

const useSoundStore = create((set, get) => ({
  sound: "grunt",
  action: () => {
    const sound = get().sound  // you still have access to state outside of it through get
    // ...
  }
})

export default useBearStore

在 react 之外使用呢?

tsx
import { createStore } from 'zustand/vanilla'

const store = createStore(() => ({ ... }))
const { getState, setState, subscribe } = store

export default store

import { useStore } from 'zustand'
import { vanillaStore } from './vanillaStore'

const useBoundStore = (selector) => useStore(vanillaStore, selector)

获取状态

tsx
// It will cause the component to update on every state change!
const state = useBearStore()

// It detects changes with strict-equality (old === new) by default, this is efficient for atomic state picks.
const bears = useBearStore((state) => state.bears)

// Object pick, re-renders the component when either state.nuts or state.honey change
const { nuts, honey } = useBearStore(
  (state) => ({ nuts: state.nuts, honey: state.honey }),
  shallow
)

// Array pick, re-renders the component when either state.nuts or state.honey change
const [nuts, honey] = useBearStore(
  (state) => [state.nuts, state.honey],
  shallow
)

// Mapped picks, re-renders the component when state.treats changes in order, count or keys
const treats = useBearStore((state) => Object.keys(state.treats), shallow)

// You may provide any custom equality function
const treats = useBearStore(
  (state) => state.treats,
  (oldTreats, newTreats) => compare(oldTreats, newTreats)
)
const increase = useBearStore((state) => state.increase)

在组件之外如何使用?

tsx
const useDogStore = create(() => ({ paw: true, snout: true, fur: true }))

// Getting non-reactive fresh state
const paw = useDogStore.getState().paw
// Listening to all changes, fires synchronously on every change
const unsub1 = useDogStore.subscribe(console.log)
// Updating state, will trigger listeners
useDogStore.setState({ paw: false })
// Unsubscribe listeners
unsub1()

// You can of course use the hook as you always would
const Component = () => {
  const paw = useDogStore((state) => state.paw)
  ...

参考文章

Zustand

https://github.com/pmndrs/zustand

标签 :
comments powered by Disqus
相关文章
用 Logseq 记笔记,从此 Networked Thinking!

attention(2023.01.07):成文时 Logseq 0.8.15 update(2023.01.11): 将 OKR 一节重写,给出 :current-page 不稳定的一个比较麻烦的解决办法。 update(2023.01.13): 已有开源贡献者着手修复该问题,:current-page 后续应该能正常使用。 🤔动机 出于数据云上不在我手上的担忧,需要一款开源本地笔记软件,最好能通过 Git 管理源文件,还能给我提供一种记笔记的新思路。

阅读更多
如何在多个编程语言间切换自如

Attention 要自由切换编程语言,必然要通过实践,编程语言之海浩瀚无边,本文会随着作者的实践而不断更新,敬请期待。 基本思路 熟悉各语言基本语法,怎么定义变量、函数、控制流等,这里有语法简介、数据结构等章节。 识别各语言的特性,为什么 Python 有元组等,也就是要知道语言的特性和高级用法等。 在熟悉基本语法时,要能搞清楚各编程语言怎么描述相同的功能的。 在识别语言特性时,要能搞清楚各编程语言处理方式上的设计哲学。

阅读更多
内存管理:分段、分区、分页

内存要怎么用起来呢?存储程序的思想,把程序放入内存,程序在CPU中取指执行! 而用户程序有逻辑地址,实际的内存是物理地址,于是先有一个地址重定位的问题。 由于程序载入内存之后,睡眠了的话,还会被移入到磁盘,因此在运行时做重定位更好,这叫做地址翻译。

阅读更多