Merge branch 'main' into v5

This commit is contained in:
daishi 2024-05-12 14:52:33 +09:00
commit 263d63dbad
19 changed files with 8364 additions and 6043 deletions

View File

@ -8,4 +8,4 @@ Fixes #
## Check List
- [ ] `yarn run prettier` for formatting code and docs
- [ ] `pnpm run prettier` for formatting code and docs

View File

@ -1,13 +1,20 @@
name: Compressed Size
on: [pull_request]
on: [ pull_request ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: preactjs/compressed-size-action@v2
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
version: 8.2.0
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- uses: preactjs/compressed-size-action@v2

View File

@ -10,17 +10,16 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
node-version: '18'
cache: yarn
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- run: yarn install --frozen-lockfile --check-files
- run: cd examples/demo && yarn install --frozen-lockfile --check-files
- name: Prettier
run: yarn prettier:ci
- name: Lint
run: yarn eslint:ci
- name: Type
run: yarn pretest
version: 8.2.0
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --frozen-lockfile
- run: pnpm test:format
- run: pnpm test:types
- run: pnpm test:lint

View File

@ -16,13 +16,16 @@ jobs:
env: [development] # [development, production]
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 8.2.0
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: yarn
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- run: yarn install --frozen-lockfile --check-files
- run: yarn build
node-version: 18
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --frozen-lockfile
- run: pnpm build
- name: Patch for DEV-ONLY
if: ${{ matrix.env == 'development' }}
run: |
@ -46,6 +49,6 @@ jobs:
NODE_ENV: ${{ matrix.env }}
- name: Test ${{ matrix.build }} ${{ matrix.env }}
run: |
yarn test:ci
pnpm test:spec
env:
NODE_ENV: ${{ matrix.env }}

View File

@ -10,17 +10,18 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
node-version: '18'
cache: yarn
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- run: yarn install --frozen-lockfile --check-files
- name: Test Build # we don't have any other workflows to test build
run: yarn build
- name: Test Default
run: yarn test:ci
version: 8.2.0
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --frozen-lockfile
- run: pnpm build # we don't have any other workflows to test build
- run: pnpm test:spec
test_matrix:
runs-on: ubuntu-latest
@ -34,14 +35,17 @@ jobs:
- 18.3.0-canary-2f8f77602-20240229
- 0.0.0-experimental-2f8f77602-20240229
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
node-version: '18'
cache: yarn
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- run: yarn install --frozen-lockfile --check-files
- name: Test ${{ matrix.react }}
version: 8.2.0
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --frozen-lockfile
- name: Test ${{ matrix.react }} ${{ matrix.devtools-skip }}
run: |
yarn add -D react@${{ matrix.react }} react-dom@${{ matrix.react }}
yarn test:ci
pnpm add -D react@${{ matrix.react }} react-dom@${{ matrix.react }}
pnpm test:spec

View File

@ -24,14 +24,17 @@ jobs:
- 4.6.4
- 4.5.5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
node-version: '18'
cache: yarn
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- run: yarn install --frozen-lockfile --check-files
- run: yarn build
version: 8.2.0
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --frozen-lockfile
- run: pnpm build
- name: Patch for Old TS
run: |
sed -i~ 's/"moduleResolution": "bundler",/"moduleResolution": "node",/' tsconfig.json
@ -39,7 +42,9 @@ jobs:
sed -i~ 's/"zustand": \["\.\/src\/index\.ts"\],/"zustand": [".\/dist\/index.d.ts"],/' tsconfig.json
sed -i~ 's/"zustand\/\*": \["\.\/src\/\*\.ts"\]/"zustand\/*": [".\/dist\/*.d.ts"]/' tsconfig.json
sed -i~ 's/"include": .*/"include": ["src\/types.d.ts", "dist\/**\/*", "tests\/**\/*"],/' tsconfig.json
pnpm json -I -f package.json -e "this.resolutions={}; this.resolutions['@types/node']='18.13.0';"
pnpm add -D @types/node@18.13.0
- name: Install old TypeScript
run: yarn add -D typescript@${{ matrix.typescript }}
run: pnpm add -D typescript@${{ matrix.typescript }}
- name: Test ${{ matrix.typescript }}
run: yarn tsc --noEmit
run: pnpm test:types

2
.gitignore vendored
View File

@ -7,8 +7,6 @@ $RECYCLE.BIN/
.DS_Store
.vscode
.docz/
package-lock.json
pnpm-lock.yaml
coverage/
.rpt2_cache/
.idea

View File

@ -65,14 +65,13 @@ you can use this suggested workflow:
- Fork this repository;
- Create a new feature branch based on the `main` branch;
- Install dependencies by running `yarn`
([version 1](https://classic.yarnpkg.com/lang/en/docs/install));
- Install dependencies by running `pnpm`;
- Create failing tests for your fix or new feature;
- Implement your changes and confirm that all test are passing.
You can run the tests continuously during development
with the `yarn test` command.
with the `pnpm test` command.
- If you want to test it in a React project:
- Either use `yarn link`, or
- Either use `pnpm link`, or
- Use the `yalc` package.
- Commit your changes (see the [committing guidelines]).
- Submit a PR for review.

View File

@ -107,12 +107,14 @@ Let's use the `createCounterStore` in our component and share it using a context
'use client'
import { type ReactNode, createContext, useRef, useContext } from 'react'
import { type StoreApi, useStore } from 'zustand'
import { useStore } from 'zustand'
import { type CounterStore, createCounterStore } from '@/stores/counter-store'
export const CounterStoreContext = createContext<StoreApi<CounterStore> | null>(
null,
export type CounterStoreApi = ReturnType<typeof createCounterStore>
export const CounterStoreContext = createContext<CounterStoreApi | undefined>(
undefined,
)
export interface CounterStoreProviderProps {
@ -122,7 +124,7 @@ export interface CounterStoreProviderProps {
export const CounterStoreProvider = ({
children,
}: CounterStoreProviderProps) => {
const storeRef = useRef<StoreApi<CounterStore>>()
const storeRef = useRef<CounterStoreApi>()
if (!storeRef.current) {
storeRef.current = createCounterStore()
}
@ -140,7 +142,7 @@ export const useCounterStore = <T,>(
const counterStoreContext = useContext(CounterStoreContext)
if (!counterStoreContext) {
throw new Error(`useCounterStore must be use within CounterStoreProvider`)
throw new Error(`useCounterStore must be used within CounterStoreProvider`)
}
return useStore(counterStoreContext, selector)
@ -194,7 +196,7 @@ export const createCounterStore = (
'use client'
import { type ReactNode, createContext, useRef, useContext } from 'react'
import { type StoreApi, useStore } from 'zustand'
import { useStore } from 'zustand'
import {
type CounterStore,
@ -202,8 +204,10 @@ import {
initCounterStore,
} from '@/stores/counter-store'
export const CounterStoreContext = createContext<StoreApi<CounterStore> | null>(
null,
export type CounterStoreApi = ReturnType<typeof createCounterStore>
export const CounterStoreContext = createContext<CounterStoreApi | undefined>(
undefined,
)
export interface CounterStoreProviderProps {
@ -213,7 +217,7 @@ export interface CounterStoreProviderProps {
export const CounterStoreProvider = ({
children,
}: CounterStoreProviderProps) => {
const storeRef = useRef<StoreApi<CounterStore>>()
const storeRef = useRef<CounterStoreApi>()
if (!storeRef.current) {
storeRef.current = createCounterStore(initCounterStore())
}
@ -231,7 +235,7 @@ export const useCounterStore = <T,>(
const counterStoreContext = useContext(CounterStoreContext)
if (!counterStoreContext) {
throw new Error(`useCounterStore must be use within CounterStoreProvider`)
throw new Error(`useCounterStore must be used within CounterStoreProvider`)
}
return useStore(counterStoreContext, selector)

View File

@ -57,10 +57,25 @@ this means your application logic does not need to be changed or mocked when wri
The mock provided below will enable the relevant test runner to reset the zustand stores after each test.
> **Warning:** In the following examples we are only supporting the curried version of create `(create()(...))`,
> since it is supported on both JavaScript and TypeScript. If you are using the uncurried version of
> `create(...)` you will need to update your hooks to use the curried version, or update the mocks in order
> to support the uncurried version.
### Shared code just for testing purposes
This shared code was added to avoid code duplication in our demo since we use the same counter store
creator for both implementations, with and without `Context` API — `createStore` and `create`, respectively.
```ts
// shared/counter-store-creator.ts
import { type StateCreator } from 'zustand'
export type CounterStore = {
count: number
inc: () => void
}
export const counterStoreCreator: StateCreator<CounterStore> = (set) => ({
count: 1,
inc: () => set((state) => ({ count: state.count + 1 })),
})
```
### Jest
@ -126,7 +141,7 @@ afterEach(() => {
```
```ts
// src/setup-jest.ts
// setup-jest.ts
import '@testing-library/jest-dom'
```
@ -137,7 +152,7 @@ import type { JestConfigWithTsJest } from 'ts-jest'
const config: JestConfigWithTsJest = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['./src/setup-jest.ts'],
setupFilesAfterEnv: ['./setup-jest.ts'],
}
export default config
@ -218,7 +233,7 @@ afterEach(() => {
> to add `import { afterEach, vi } from 'vitest'` at the top.
```ts
// __mocks__/vitest-env.d.ts
// global.d.ts
/// <reference types="vite/client" />
/// <reference types="vitest/globals" />
```
@ -227,10 +242,10 @@ afterEach(() => {
> need to remove `/// <reference types="vitest/globals" />`.
```ts
// src/setup-vitest.ts
// setup-vitest.ts
import '@testing-library/jest-dom'
vi.mock('zustand') // to make it works like Jest (auto-mocking)
vi.mock('zustand') // to make it work like Jest (auto-mocking)
```
> **Note**: without [globals configuration](https://vitest.dev/config/#globals) enabled, we need
@ -278,39 +293,47 @@ export const counterStoreCreator: StateCreator<CounterStore> = (set) => ({
// stores/user-counter-store.ts
import { create } from 'zustand'
import { type CounterStore, counterStoreCreator } from './counter-store-creator'
import {
type CounterStore,
counterStoreCreator,
} from '../shared/counter-store-creator'
export const useCounterStore = create<CounterStore>()(counterStoreCreator)
```
```tsx
// stores/use-counter-store-context.tsx
import {
type PropsWithChildren,
createContext,
useContext,
useRef,
} from 'react'
import { type StoreApi, createStore } from 'zustand'
// contexts/use-counter-store-context.tsx
import { type ReactNode, createContext, useContext, useRef } from 'react'
import { createStore } from 'zustand'
import { useStoreWithEqualityFn } from 'zustand/traditional'
import { shallow } from 'zustand/shallow'
import { type CounterStore, counterStoreCreator } from './counter-store-creator'
import {
type CounterStore,
counterStoreCreator,
} from '../shared/counter-store-creator'
export const createCounterStore = () => {
return createStore<CounterStore>(counterStoreCreator)
}
export const CounterStoreContext = createContext<StoreApi<CounterStore>>(
null as never,
export type CounterStoreApi = ReturnType<typeof createCounterStore>
export const CounterStoreContext = createContext<CounterStoreApi | undefined>(
undefined,
)
export type CounterStoreProviderProps = PropsWithChildren
export interface CounterStoreProviderProps {
children: ReactNode
}
export const CounterStoreProvider = ({
children,
}: CounterStoreProviderProps) => {
const counterStoreRef = useRef(createCounterStore())
const counterStoreRef = useRef<CounterStoreApi>()
if (!counterStoreRef.current) {
counterStoreRef.current = createCounterStore()
}
return (
<CounterStoreContext.Provider value={counterStoreRef.current}>
@ -400,7 +423,7 @@ const renderCounter = () => {
import {
CounterStoreProvider,
useCounterStoreContext,
} from '../../stores/use-counter-store-context'
} from '../../contexts/use-counter-store-context'
const Counter = () => {
const { count, inc } = useCounterStoreContext((state) => state)
@ -470,8 +493,8 @@ const renderCounterWithContext = () => {
**CodeSandbox Demos**
- Jest Demo: https://codesandbox.io/p/sandbox/zustand-jest-demo-twkypn
- Vitest Demo: https://codesandbox.io/p/sandbox/zustand-vitest-demo-ph5gnj
- Jest Demo: https://stackblitz.com/edit/jest-zustand
- Vitest Demo: https://stackblitz.com/edit/vitest-zustand
## References

View File

@ -131,7 +131,7 @@ You can also use [Ramda](https://ramdajs.com/):
```ts
ramdaInc: () =>
set(R.over(R.lensPath(["deep", "nested", "obj", "count"]), (c) => c + 1)),
set(R.modifyPath(["deep", "nested", "obj", "count"], (c) => c + 1)),
```
Both ramda and optics-ts also work with types.

View File

@ -20,7 +20,7 @@ This can be done using third-party libraries created by the community.
- [@dhmk/zustand-lens](https://github.com/dhmk083/dhmk-zustand-lens) — Lens support for Zustand.
- [@liveblocks/zustand](https://github.com/liveblocks/liveblocks/tree/main/packages/liveblocks-zustand) — Liveblocks middleware to make your application multiplayer.
- [auto-zustand-selectors-hook](https://github.com/Albert-Gao/auto-zustand-selectors-hook) — Automatic generation of Zustand hooks with Typescript support.
- [derive-zustand](https://github.com/dai-shi/derive-zustand) — A function to create a derived Zustand store from other Zustand stores.
- [derive-zustand](https://github.com/zustandjs/derive-zustand) — A function to create a derived Zustand store from other Zustand stores.
- [geschichte](https://github.com/BowlingX/geschichte) — Zustand and Immer-based hook to manage query parameters.
- [leiten-zustand](https://github.com/hecmatyar/leiten-zustand) — Cleans your store from boilerplate for requests and data transformation.
- [mobz](https://github.com/2A5F/Mobz) — Zustand-style MobX API.
@ -30,14 +30,15 @@ This can be done using third-party libraries created by the community.
- [simple-zustand-devtools](https://github.com/beerose/simple-zustand-devtools) — 🐻⚛️ Inspect your Zustand store in React DevTools.
- [solid-zustand](https://github.com/wobsoriano/solid-zustand) — State management in Solid using Zustand.
- [use-broadcast-ts](https://github.com/Romainlg29/use-broadcast) — Zustand middleware to share state between tabs.
- [use-zustand](https://github.com/dai-shi/use-zustand) — Another custom hook to use Zustand vanilla store.
- [use-zustand](https://github.com/zustandjs/use-zustand) — Another custom hook to use Zustand vanilla store.
- [vue-zustand](https://github.com/wobsoriano/vue-zustand) — State management solution for Vue based on Zustand.
- [zoov](https://github.com/InfiniteXyy/zoov) — State management solution based on Zustand with Module-like API.
- [zundo](https://github.com/charkour/zundo) — 🍜 Undo and redo middleware for Zustand, enabling time-travel in your apps.
- [zukeeper](https://github.com/oslabs-beta/Zukeeper) - Native devtools with state and action tracking, diffing, tree display, and time travel
- [zustand-ards](https://github.com/ivoilic/zustand-ards) - 💁 Simple opinionated utilities for example alternative selector formats and default shallow hooks
- [zustand-constate](https://github.com/ntvinhit/zustand-constate) — Context-based state management based on Zustand and taking ideas from Constate.
- [zustand-computed](https://github.com/chrisvander/zustand-computed) — A Zustand middleware to create computed states.
- [zustand-constate](https://github.com/ntvinhit/zustand-constate) — Context-based state management based on Zustand and taking ideas from Constate.
- [zustand-context](https://github.com/fredericoo/zustand-context) — Create a zustand store in React Context, containing an initial value, or use it in your components with isolated, mockable instances.
- [zustand-di](https://github.com/charkour/zustand-di) - use react props to init zustand stores
- [zustand-forms](https://github.com/Conduct/zustand-forms) — Fast, type safe form states as Zustand stores.
- [zustand-middleware-computed-state](https://github.com/cmlarsen/zustand-middleware-computed-state) — A dead simple middleware for adding computed state to Zustand.
@ -48,6 +49,7 @@ This can be done using third-party libraries created by the community.
- [zustand-querystring](https://github.com/nitedani/zustand-querystring) — A Zustand middleware that syncs the store with the querystring.
- [zustand-rx](https://github.com/patdx/zustand-rx) — A Zustand middleware enabling you to subscribe to a store as an RxJS Observable.
- [zustand-saga](https://github.com/Nowsta/zustand-saga) — A Zustand middleware for redux-saga (minus redux).
- [zustand-slices](https://github.com/zustandjs/zustand-slices) — A slice utility for Zustand.
- [zustand-store-addons](https://github.com/Diablow/zustand-store-addons) — React state management addons for Zustand.
- [zustand-sync-tabs](https://github.com/mayank1513/zustand-sync-tabs) — Zustand middleware to easily sync Zustand state between tabs/windows/iframes with same origin.
- [zustand-vue](https://github.com/AwesomeDevin/zustand-vue) - State management for vue (Vue3 / Vue2) based on zustand.

View File

@ -9,12 +9,14 @@
"lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"packageManager": "pnpm@8.15.0",
"dependencies": {
"@react-three/drei": "^9.78.2",
"@react-three/fiber": "^8.13.7",
"@react-three/postprocessing": "^2.14.13",
"@types/three": "^0.155.0",
"meshline": "^3.1.6",
"postprocessing": "^6.35.4",
"prism-react-renderer": "^2.0.6",
"prismjs": "^1.29.0",
"react": "^18.2.0",

2716
examples/demo/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,12 @@
{
"name": "zustand",
"description": "🐻 Bear necessities for state management in React",
"private": true,
"type": "commonjs",
"version": "5.0.0-alpha.6",
"publishConfig": {
"tag": "next"
},
"description": "🐻 Bear necessities for state management in React",
"main": "./index.js",
"types": "./index.d.ts",
"typesVersions": {
@ -55,7 +56,7 @@
"sideEffects": false,
"scripts": {
"prebuild": "shx rm -rf dist",
"build": "concurrently -m 8 'yarn:build:*'",
"build": "pnpm run prebuild && pnpm run '/^build:.*/' && pnpm run postbuild",
"build:base": "rollup -c",
"build:vanilla": "rollup -c --config-vanilla",
"build:react": "rollup -c --config-react",
@ -65,14 +66,15 @@
"build:vanilla:shallow": "rollup -c --config-vanilla_shallow",
"build:react:shallow": "rollup -c --config-react_shallow",
"build:traditional": "rollup -c --config-traditional",
"postbuild": "yarn patch-d-ts && yarn copy && yarn patch-old-ts && yarn patch-esm-ts",
"build:context": "rollup -c --config-context",
"postbuild": "pnpm patch-d-ts && pnpm copy && pnpm patch-old-ts && pnpm patch-esm-ts",
"prettier": "prettier \"*.{js,json,md}\" \"{examples,src,tests,docs}/**/*.{js,jsx,ts,tsx,md,mdx}\" --write",
"prettier:ci": "prettier '*.{js,json,md}' '{examples,src,tests,docs}/**/*.{js,jsx,ts,tsx,md,mdx}' --list-different",
"eslint": "eslint --no-eslintrc --c .eslintrc.json --fix '*.{js,json,ts}' '{src,tests}/**/*.{ts,tsx}'",
"eslint:ci": "eslint --no-eslintrc --c .eslintrc.json '*.{js,json,ts}' '{src,tests}/**/*.{ts,tsx}'",
"pretest": "tsc",
"test": "vitest --ui --coverage",
"test:ci": "vitest",
"test": "pnpm run '/^test:.*/'",
"test:format": "prettier '*.{js,json,md}' '{examples,src,tests,docs}/**/*.{js,jsx,ts,tsx,md,mdx}' --list-different",
"test:types": "tsc --noEmit",
"test:lint": "eslint --no-eslintrc --c .eslintrc.json '*.{js,json,ts}' '{src,tests}/**/*.{ts,tsx}'",
"test:spec": "vitest",
"patch-d-ts": "node -e \"var {entries}=require('./rollup.config.js');require('shelljs').find('dist/**/*.d.ts').forEach(f=>{entries.forEach(({find,replacement})=>require('shelljs').sed('-i',new RegExp(' from \\''+find.source.slice(0,-1)+'\\';$'),' from \\''+replacement+'\\';',f));require('shelljs').sed('-i',/ from '(\\.[^']+)\\.ts';$/,' from \\'\\$1\\';',f)})\"",
"copy": "shx cp -r dist/src/* dist/esm && shx cp -r dist/src/* dist && shx rm -rf dist/src && shx rm -rf dist/{src,tests} && shx cp package.json readme.md LICENSE dist && json -I -f dist/package.json -e \"this.private=false; this.devDependencies=undefined; this.optionalDependencies=undefined; this.scripts=undefined; this.prettier=undefined;\"",
"patch-old-ts": "shx touch dist/ts_version_4.5_and_above_is_required.d.ts",
@ -107,6 +109,7 @@
"url": "https://github.com/pmndrs/zustand/issues"
},
"homepage": "https://github.com/pmndrs/zustand",
"packageManager": "pnpm@8.15.0",
"devDependencies": {
"@redux-devtools/extension": "^3.3.0",
"@rollup/plugin-alias": "^5.1.0",
@ -122,7 +125,6 @@
"@typescript-eslint/parser": "^7.1.0",
"@vitest/coverage-v8": "^1.4.0",
"@vitest/ui": "^1.4.0",
"concurrently": "^8.2.2",
"esbuild": "^0.20.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
@ -141,6 +143,7 @@
"redux": "^5.0.1",
"rollup": "^4.12.0",
"rollup-plugin-esbuild": "^6.1.1",
"shelljs": "^0.8.5",
"shx": "^0.3.4",
"typescript": "^5.3.3",
"use-sync-external-store": "^1.2.0",
@ -165,6 +168,5 @@
"use-sync-external-store": {
"optional": true
}
},
"packageManager": "yarn@1.22.21+sha256.dbed5b7e10c552ba0e1a545c948d5473bc6c5a28ce22a8fd27e493e3e5eb6370"
}
}

5490
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@ Don't disregard it because it's cute. It has quite the claws, lots of time was s
You can try a live demo [here](https://githubbox.com/pmndrs/zustand/tree/main/examples/demo).
```bash
npm install zustand # or yarn add zustand or pnpm add zustand
npm i zustand
```
:warning: This readme is written for JavaScript users. If you are a TypeScript user, be sure to check out our [TypeScript Usage section](#typescript-usage).

3792
yarn.lock

File diff suppressed because it is too large Load Diff