Merge branch 'main' into v5

This commit is contained in:
daishi 2024-05-22 09:30:42 +09:00
commit 4de1d1ff29
5 changed files with 430 additions and 255 deletions

View File

@ -32,8 +32,8 @@ jobs:
- 18.0.0
- 18.1.0
- 18.2.0
- 18.3.0-canary-2f8f77602-20240229
- 0.0.0-experimental-2f8f77602-20240229
- 19.0.0-rc-8f3c0525f9-20240521
- 0.0.0-experimental-8f3c0525f9-20240521
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2

View File

@ -80,9 +80,9 @@ const useBoundStore = create<{ foo: number }>()((_, get) => ({
This code compiles. But if we run it, we'll get an exception: "Uncaught TypeError: Cannot read properties of undefined (reading 'foo')". This is because `get` would return `undefined` before the initial state is created (hence you shouldn't call `get` when creating the initial state). The types promise that `get` will never return `undefined` but it does initially, which means Zustand failed to implement it.
And of course Zustand failed because it's impossible to implement `create` the way types promise (in the same way it's impossible to implement `createFoo`). In other words we don't have a type to express the actual `create` we have implemented. We can't type `get` as `() => T | undefined` because it would cause inconveince and it still won't be correct as `get` is indeed `() => T` eventually, just if called synchronously it would be `() => undefined`. What we need is some kind of TypeScript feature that allows us to type `get` as `(() => T) & WhenSync<() => undefined>`, which of course is extremly far-fetched.
And of course Zustand failed because it's impossible to implement `create` the way types promise (in the same way it's impossible to implement `createFoo`). In other words we don't have a type to express the actual `create` we have implemented. We can't type `get` as `() => T | undefined` because it would cause inconvenience and it still won't be correct as `get` is indeed `() => T` eventually, just if called synchronously it would be `() => undefined`. What we need is some kind of TypeScript feature that allows us to type `get` as `(() => T) & WhenSync<() => undefined>`, which of course is extremely far-fetched.
So we have two problems: lack of inference and unsoundness. Lack of inference can be solved if TypeScript can improves its inference for invariants. And unsoundness can be solved if TypeScript introduces something like `WhenSync`. To work around lack of inference we manually annotate the state type. And we can't work around unsoundness, but it's not a big deal because it's not much, calling `get` synchronously anyway doesn't make sense.
So we have two problems: lack of inference and unsoundness. Lack of inference can be solved if TypeScript can improve its inference for invariants. And unsoundness can be solved if TypeScript introduces something like `WhenSync`. To work around lack of inference we manually annotate the state type. And we can't work around unsoundness, but it's not a big deal because it's not much, calling `get` synchronously anyway doesn't make sense.
</details>
@ -208,7 +208,7 @@ const useBearStore = create<BearState>()(
)
```
Also, we recommend using `devtools` middleware as last as possible. For example, when you use it with `immer` as a middleware, it should be `immer(devtools(...))` and not `devtools(immer(...))`. This is because`devtools` mutates the `setState` and adds a type parameter on it, which could get lost if other middlewares (like `immer`) also mutate `setState` before `devtools`. Hence using `devtools` at the end makes sure that no middlewares mutate `setState` before it.
Also, we recommend using `devtools` middleware as last as possible. For example, when you use it with `immer` as a middleware, it should be `devtools(immer(...))` and not `immer(devtools(...))`. This is because`devtools` mutates the `setState` and adds a type parameter on it, which could get lost if other middlewares (like `immer`) also mutate `setState` before `devtools`. Hence using `devtools` at the end makes sure that no middlewares mutate `setState` before it.
## Authoring middlewares and advanced usage

View File

@ -19,6 +19,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.
- [@prncss-xyz/zustand-optics](https://github.com/prncss-xyz/zustand-optics) — An adapter for [optics-ts](https://github.com/akheron/optics-ts).
- [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/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.

View File

@ -73,7 +73,7 @@
"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",
"test:spec": "vitest run",
"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",
@ -115,38 +115,38 @@
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.5",
"@rollup/plugin-typescript": "^11.1.6",
"@testing-library/react": "^14.2.1",
"@types/node": "^20.11.24",
"@types/react": "^18.2.61",
"@types/react-dom": "^18.2.19",
"@testing-library/react": "^15.0.7",
"@types/node": "^20.12.12",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0",
"@types/use-sync-external-store": "^0.0.6",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"@vitest/coverage-v8": "^1.4.0",
"@vitest/ui": "^1.4.0",
"esbuild": "^0.20.1",
"eslint": "^8.57.0",
"@typescript-eslint/eslint-plugin": "^7.10.0",
"@typescript-eslint/parser": "^7.10.0",
"@vitest/coverage-v8": "^1.6.0",
"@vitest/ui": "^1.6.0",
"esbuild": "^0.21.3",
"eslint": "8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-vitest": "^0.3.22",
"immer": "^10.0.3",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-vitest": "^0.5.4",
"immer": "^10.1.1",
"jsdom": "^24.0.0",
"json": "^11.0.0",
"prettier": "^3.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "19.0.0-rc-81c5ff2e04-20240521",
"react-dom": "19.0.0-rc-81c5ff2e04-20240521",
"redux": "^5.0.1",
"rollup": "^4.12.0",
"rollup": "^4.17.2",
"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",
"vitest": "^1.4.0"
"typescript": "^5.4.5",
"use-sync-external-store": "^1.2.2",
"vitest": "^1.6.0"
},
"peerDependencies": {
"@types/react": ">=18.0.0",

632
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff