Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

zustand

Package Overview
Dependencies
Maintainers
1
Versions
142
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zustand - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

2

dist/cjs/index.d.ts

@@ -21,2 +21,2 @@ export declare type State = Record<string, any>;

}
export default function create<TState extends State>(createState: (set: SetState<State>, get: GetState<State>) => TState): [UseStore<TState>, StoreApi<TState>];
export default function create<TState extends State>(createState: (set: SetState<State>, get: GetState<State>, api: any) => TState): [UseStore<TState>, StoreApi<TState>];

@@ -99,2 +99,3 @@ 'use strict';

return selector ? subscribe( // Truthy check because it might be possible to set selectorRef to
// undefined and call this subscriber before it resubscribes
function () {

@@ -108,4 +109,3 @@ return selectorRef.current ? selectorRef.current(state) : state;

var state = createState(setState, getState);
return [useStore, {
var api = {
destroy: destroy,

@@ -115,5 +115,7 @@ getState: getState,

subscribe: subscribe
}];
};
var state = createState(setState, getState, api);
return [useStore, api];
}
module.exports = create;

@@ -21,2 +21,2 @@ export declare type State = Record<string, any>;

}
export default function create<TState extends State>(createState: (set: SetState<State>, get: GetState<State>) => TState): [UseStore<TState>, StoreApi<TState>];
export default function create<TState extends State>(createState: (set: SetState<State>, get: GetState<State>, api: any) => TState): [UseStore<TState>, StoreApi<TState>];

@@ -85,2 +85,3 @@ import { useRef, useReducer, useLayoutEffect } from 'react';

return selector ? subscribe( // Truthy check because it might be possible to set selectorRef to
// undefined and call this subscriber before it resubscribes
() => selectorRef.current ? selectorRef.current(state) : state, dispatch) : subscribe(dispatch); // Only resubscribe to the store when changing selector from function to

@@ -92,4 +93,3 @@ // undefined or undefined to function

let state = createState(setState, getState);
return [useStore, {
let api = {
destroy,

@@ -99,5 +99,7 @@ getState,

subscribe
}];
};
let state = createState(setState, getState, api);
return [useStore, api];
}
export default create;
{
"name": "zustand",
"version": "0.2.0",
"version": "0.2.1",
"description": "🐻 Bear necessities for state management in React",

@@ -74,5 +74,2 @@ "main": "dist/cjs/index.js",

"tests/**/*.{js,ts,tsx}"
],
"setupFilesAfterEnv": [
"<rootDir>/setupTests.js"
]

@@ -86,8 +83,7 @@ },

"@babel/preset-env": "^7.4.3",
"@testing-library/react": "^8.0.1",
"@types/jest": "^24.0.11",
"@types/react": "^16.8.13",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"husky": "^1.3.1",
"jest": "^24.7.1",
"husky": "^2.3.0",
"jest": "^24.8.0",
"lint-staged": "^8.1.5",

@@ -97,10 +93,9 @@ "prettier": "^1.17.0",

"react-dom": "^16.8.6",
"react-testing-library": "^6.1.2",
"rimraf": "^2.6.3",
"rollup": "^1.10.0",
"rollup": "^1.13.1",
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-node-resolve": "^4.2.3",
"rollup-plugin-size-snapshot": "^0.8.0",
"rollup-plugin-typescript2": "^0.20.1",
"typescript": "^3.4.3"
"rollup-plugin-node-resolve": "^5.0.1",
"rollup-plugin-size-snapshot": "^0.9.0",
"rollup-plugin-typescript2": "^0.21.1",
"typescript": "^3.5.1"
},

@@ -107,0 +102,0 @@ "peerDependencies": {

@@ -9,19 +9,26 @@ <p align="center">

Small, fast and scaleable bearbones state-management solution. Has a comfy api based on hooks, isn't that boilerplatey or opinionated, but still just enough to be explicit and flux-like, not context based (no reliance on providers, breaches reconciler boundaries), and is cross-platform to boot. Make your paws dirty with a small live demo [here](https://codesandbox.io/s/v8pjv251w7).
Small, fast and scaleable bearbones state-management solution. Has a comfy api based on hooks, isn't that boilerplatey or opinionated, but still just enough to be explicit and flux-like. Make your paws dirty with a small live demo [here](https://codesandbox.io/s/v8pjv251w7).
#### Create a store (or multiple, up to you...)
#### Why zustand over redux? This lib ...
You could be in global or component scope, manage your store anywhere you want!
1. is simpler and un-opinionated
2. makes hooks the primary means of consuming state
3. isn't dependent on actions, types & dispatch
4. supports [mixed reconcilers](https://github.com/konvajs/react-konva/issues/188)
5. has a solution for rapidpy changing state (look for transient updates)
### How to use it
#### First create a store (or multiple, up to you...)
Your store is a hook! Name it anything you like. Everything inside `create` is your state. There are no rules, you can put anything in it. Actions are not special, you don't need to group them. The `set` function works like Reacts setState, it *merges* state.
```jsx
import create from 'zustand'
// You store is a hook! Name it as you like
const [useStore] = create(set => ({
// Everything in here is your state
count: 1,
actions: {
// You don't have to nest your actions, but makes it easier to fetch them later on
inc: () => set(state => ({ count: state.count + 1 })), // same semantics as setState
dec: () => set(state => ({ count: state.count - 1 })), // ... it *merges* state
inc: () => set(state => ({ count: state.count + 1 })),
dec: () => set(state => ({ count: state.count - 1 })),
},

@@ -31,9 +38,8 @@ }))

#### Bind components
#### Then bind components with the resulting hook, that's it!
Look Ma, no providers!
Use the hook anywhere, you are not tied to providers and sub-trees. Once you have selected state your component will re-render whenever your selection changes in the store.
```jsx
function Counter() {
// Will only re-render the component when "count" changes
const count = useStore(state => state.count)

@@ -44,3 +50,2 @@ return <h1>{count}</h1>

function Controls() {
// "actions" isn't special, in this case it makes fetching updaters easier
const actions = useStore(state => state.actions)

@@ -68,3 +73,3 @@ return (

It's just like mapStateToProps in Redux. zustand will run a small shallow equal over the object you return. Of course, it won't cause re-renders if these properties aren't changed in the state model.
Just like with Reduxes mapStateToProps, useStore can select state, either atomically or by returning an object. It will run a small shallow-equal test over the results you return and update the component on changes only.

@@ -75,3 +80,3 @@ ```jsx

Or, if you prefer, atomic selects do the same ...
Atomic selects do the same ...

@@ -85,3 +90,3 @@ ```jsx

Since you can create as many stores as you like, forwarding a result into another selector is straight forward.
Since you can create as many stores as you like, forwarding results to succeeding selectors is as natural as it gets.

@@ -95,3 +100,3 @@ ```jsx

Flux stores usually call the selector on every render-pass. Most of the time this isn't much of a problem, but when your selectors are computationally expensive, or when you know the component renders a lot (for instance react-motion calling it 60 times per second for animation purposes) you may want to optimize it.
Say you select a piece of state ...

@@ -102,3 +107,3 @@ ```js

In this case the selector `state => state.foo[props.id]` will run on every state change, as well as every time the component renders. This isn't expensive at all, but let's optimize it for arguments sake.
Your selector (`state => state.foo[props.id]`) will run on every state change, as well as every time the component renders. It isn't that expensive in this case, but let's optimize it for arguments sake.

@@ -112,3 +117,3 @@ You can either pass a static reference:

Or an optional dependencies array to let Zustand know when the selector updates:
Or an optional dependencies array to let zustand know when the selector needs to update:

@@ -119,3 +124,3 @@ ```js

From there on your selector will only run when either state changes, or the selector itself.
From now on your selector is memoized and will only run when either the state changes, or the selector itself.

@@ -128,9 +133,6 @@ ## Async actions

const [useStore] = create(set => ({
result: '',
json: {},
fetch: async url => {
const response = await fetch(url)
const json = await response.json()
set({ result: json })
},
}))
set({ json: await response.json() })
```

@@ -140,3 +142,3 @@

The `set` function already allows functional update `set(state => result)` but should there be cases where you need to access outside of it you have an optional `get`, too.
`set` allows fn-updates `set(state => result)`, but you still have access to state outside of it through `get`.

@@ -148,5 +150,2 @@ ```jsx

const text = get().text
...
}
}))
```

@@ -156,3 +155,3 @@

Having to build nested structures bearhanded is one of the more tiresome aspects of reducing state. Have you tried [immer](https://github.com/mweststrate/immer)? It is a tiny package that allows you to work with immutable state in a more convenient way. You can easily extend your store with it.
Reducing nested structures is tiresome. Have you tried [immer](https://github.com/mweststrate/immer)?

@@ -164,16 +163,7 @@ ```jsx

set: fn => set(produce(fn)),
nested: {
structure: {
constains: {
a: "value"
}
}
},
nested: { structure: { constains: { a: "value" } } },
}))
const set = useStore(state => state.set)
set(draft => {
draft.nested.structure.contains.a.value = false
draft.nested.structure.contains.anotherValue = true
})
set(state => void state.nested.structure.contains = null)
```

@@ -184,6 +174,3 @@

```jsx
const types = {
increase: "INCREASE",
decrease: "DECREASE"
}
const types = { increase: "INCREASE", decrease: "DECREASE" }

@@ -211,14 +198,15 @@ const reducer = (state, { type, by = 1 }) => {

```jsx
const [, api] = create({ n: 0 })
const [, api] = create({ a: 1, b: 2, c: 3 })
// Getting fresh state
const num = api.getState().n
// Listening to changes
const unsub = api.subscribe(state => console.log(state.n))
// And with a selector
const unsub2 = api.subscribe(state => state.n, n => console.log(n))
// Listening to all changes, fires on every dispatch
const unsub1 = api.subscribe(state => console.log("state changed", state))
// Listening to selected changes
const unsub2 = api.subscribe(state => state.a, a => console.log("a changed", a))
// Updating state, will trigger listeners
api.setState({ n: 1 })
// Unsubscribing listener
unsub()
api.setState({ a: 1 })
// Unsubscribe listeners
unsub1()
unsub2()
// Destroying the store (removing all listeners)

@@ -228,4 +216,20 @@ api.destroy()

## Transient updates (for often occuring state-changes)
The api signature of subscribe([selector,] callback):unsub allows you to easily bind a component to a store without forcing it to re-render on state changes, you will be notified in a callback instead. Best combine it with useEffect. This can make a [drastic](https://codesandbox.io/s/peaceful-johnson-txtws) performance difference when you are allowed to mutate the view directly.
```jsx
const [useStore, api] = create(set => ({ [0]: [-10, 0], [1]: [10, 5], ... }))
function Component({ id }) {
// Fetch initial state
const xy = useRef(api.getState()[id])
// Connect to the store on mount, disconnect on unmount, catch state-changes in a callback
useEffect(() => api.subscribe(state => state[id], coords => (xy.current = coords)), [id])
```
## Middleware
You can functionally compose your store any way you like.
```jsx

@@ -232,0 +236,0 @@ const logger = fn => (set, get) => fn(args => {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc