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

目录

计数器

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(...)

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 之外使用呢?

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)

获取状态

// 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)

在组件之外如何使用?

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

相关文章

如何自己本地编译 OpenWrt ?

感觉不如直接下载,然后用转换工具把 img 搞成 vmfs,见linux - VMware安装OpenWrt,工具下载链接https://www.starwindsoftware.com/tmplink/starwindconverter.exe。 关于系统 LEAN 的不行,还是 ImmortalWrt 更好!还可直接下载 vmfs,注意系统日志等级它默认的 debug 可不行。 关于上网控制插件,注意会和广告过滤 ACC 加速等冲突,有舍有得啊,openwrt上网时间控制为什么设置后无效-OPENWRT专版-恩山无线论坛 (right.com.cn)。 老老实实用 clash for windows 了,OpenWrt 很不稳定啊,github 时好时坏。

阅读更多
并查集

并查集三步走 并查集,开始的时候大家都是孤岛,根节点就是自己,然后我们不断地合并、修改指针,直到所有边都访问到。 数组初始化,每个节点的 parent 指针都指向自己。数组 roots 存放所有节点的祖先节点(根节点,路径压缩)【如果要求子集中元素数量,那么还要再创建一个 counts 数组,存储一份子集元素中的数量,需要在 union 中更新】。 根据所有相连的边,不断地进行查找、合并。 查找用递归、同时能修改查找路径上的所有节点的 parent 指针,合并前先调用查找然后看是否同一子图,是则合并失败,不是则直接将 parent 指针修改一下即可。 **有向图是否有环?**拓扑排序 DAG !

阅读更多
如何在 React 中轻松路由?使用 React Router!

开始 import React from "react"; import ReactDOM from "react-dom/client"; import { createBrowserRouter, RouterProvider, } from "react-router-dom"; import Root from "./routes/root"; const router = createBrowserRouter([ { path: "/", element: <Root />, }, ]); ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> ); root 路由比较特殊。 Not Found import ErrorPage from "./error-page"; const router = createBrowserRouter([ { path: "/", element: <Root />, **errorElement: <ErrorPage />,** }, ]); ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> ); 嵌套路由 让 <Contact /> 渲染在 <Root /> 的 children(<Outlet />) 中: const router = createBrowserRouter([ { path: "/", element: <Root />, errorElement: <ErrorPage />, **children**: [ { path: "contacts/:contactId", element: <Contact />, }, ], }, ]); 使用 Layout 也能解决。

阅读更多