mirror of
https://github.com/pmndrs/zustand.git
synced 2025-12-08 19:45:52 +00:00
Merge branch 'main' into v5
This commit is contained in:
commit
263d63dbad
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@ -8,4 +8,4 @@ Fixes #
|
||||
|
||||
## Check List
|
||||
|
||||
- [ ] `yarn run prettier` for formatting code and docs
|
||||
- [ ] `pnpm run prettier` for formatting code and docs
|
||||
|
||||
15
.github/workflows/compressed-size-action.yml
vendored
15
.github/workflows/compressed-size-action.yml
vendored
@ -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
|
||||
|
||||
25
.github/workflows/lint-and-type.yml
vendored
25
.github/workflows/lint-and-type.yml
vendored
@ -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
|
||||
|
||||
15
.github/workflows/test-multiple-builds.yml
vendored
15
.github/workflows/test-multiple-builds.yml
vendored
@ -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 }}
|
||||
|
||||
42
.github/workflows/test-multiple-versions.yml
vendored
42
.github/workflows/test-multiple-versions.yml
vendored
@ -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
|
||||
|
||||
23
.github/workflows/test-old-typescript.yml
vendored
23
.github/workflows/test-old-typescript.yml
vendored
@ -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
2
.gitignore
vendored
@ -7,8 +7,6 @@ $RECYCLE.BIN/
|
||||
.DS_Store
|
||||
.vscode
|
||||
.docz/
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
coverage/
|
||||
.rpt2_cache/
|
||||
.idea
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
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
24
package.json
24
package.json
@ -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
5490
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -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).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user