如何在 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

相关文章

什么软件才能让你的 macOS 更好用?

动机 起因是我重置了系统,然后发现过去的习惯都要重新来一遍,于是为什么不写一篇文章呢? brew install --cask microsoft-edge calibre sogouinput mos snipaste iina iterm2 rectangle 这里先给出一份 CheckList: 软件 clash for windows homebrew microsoft onenote & outlook & edge wechat & qq sogouinput、微信输入法 Desktop Pets:App Store 上的有趣软件,养一个电子宠物吧 Notion:必备人生管理软件,管理你的任务、物品、健身情况等,自定义能力超强的数据库 阿里云盘:不限速云盘 Calibre:电子书管理器 mos: 鼠标与触控板方向不一致的解决方案 Snipaste:截图贴图 iina:超好用的播放器,配合网络上资源站的视频地址,完全不会发热 iterm2:可以透明背景、图片背景的终端 Lens:管理 k8s 神器 Rectangle:向 windows 一样排布窗口 Paragon NTFS for Mac:希捷官网下载是免费的 软件和固件下载 | Support Seagate US 系统设置:键盘快捷键、触发角、默认网页浏览器、调度中心使窗口按应用程序成组 ActivityWatch:时间追踪工具 Typora:markdown 编辑器,剪贴板的图片能给你自动复制到当前文件夹下,很适合本地写博客 Squash:图片压缩工具 macOS Assistant: macOS 小助手,一键 bypass 签名 LocalSend:本地传输文件,特别是往安卓设备传输东西 浏览器插件 简悦:纯净阅读 Adblock plus:屏蔽广告 Dark Reader:暗黑模式 Menu fish:古诗词标签页 Relingo:英语生词自动标记 Wayback Machine:网站记录备份 Stylus:重新编辑网站 CSS 样式 Wappalyzer:网站使用了哪些技术栈 Web Clipper(配合语雀):剪藏 FireShot:截屏 篡改猴(浏览器同步脚本) Microsoft编辑器:检查拼写和语法 命令行 oh-my-zsh:一定要用 zsh Roboto Mono for powerline 字体:在 iterm2 中设置 zsh 插件 zsh-syntax-highlighting zsh-autosuggestions spaceship-ember spaceship-vi-mode autojump:j neovim:nvim 开发 TabNine:GitHub Copilot 平替 visual-studio-code:开发必备 主旨 ZSH 配置 Spaceship 安装与配置 https://github.com/spaceship-prompt/spaceship-prompt

阅读更多
如何在 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 也能解决。

阅读更多
MacBook 上安装 ArchLinux 双系统

动机 希望将闲置的 2018 款 MBP 利用起来,整成一台 Linux 服务器就好了,因为 macOS 上的 Docker 非常难用,再加上我比较爱折腾,于是有了这个想法。 主要参考这个 wiki:https://wiki.t2linux.org Tip

阅读更多