๐Ÿป Bear necessities for state management in React

Related tags

React zustand
Overview

Build Status Build Size Version Downloads Discord Shield

A small, fast and scaleable bearbones state-management solution. Has a comfy api based on hooks, isn't boilerplatey or opinionated, but still just enough to be explicit and flux-like.

Don't disregard it because it's cute. It has quite the claws, lots of time was spent to deal with common pitfalls, like the dreaded zombie child problem, react concurrency, and context loss between mixed renderers. It may be the one state-manager in the React space that gets all of these right.

You can try a live demo here.

npm install zustand

First create a store

Your store is a hook! You can put anything in it: primitives, objects, functions. The set function merges state.

import create from 'zustand'

const useStore = create(set => ({
  bears: 0,
  increasePopulation: () => set(state => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 })
}))

Then bind your components, and that's it!

Use the hook anywhere, no providers needed. Select your state and the component will re-render on changes.

function BearCounter() {
  const bears = useStore(state => state.bears)
  return <h1>{bears} around here ...</h1>
}

function Controls() {
  const increasePopulation = useStore(state => state.increasePopulation)
  return <button onClick={increasePopulation}>one up</button>
}

Why zustand over react-redux?


Recipes

Fetching everything

You can, but bear in mind that it will cause the component to update on every state change!

const state = useStore()

Selecting multiple state slices

It detects changes with strict-equality (old === new) by default, this is efficient for atomic state picks.

const nuts = useStore(state => state.nuts)
const honey = useStore(state => state.honey)

If you want to construct a single object with multiple state-picks inside, similar to redux's mapStateToProps, you can tell zustand that you want the object to be diffed shallowly by passing an alternative equality function.

import shallow from 'zustand/shallow'

// Object pick, re-renders the component when either state.nuts or state.honey change
const { nuts, honey } = useStore(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] = useStore(state => [state.nuts, state.honey], shallow)

// Mapped picks, re-renders the component when state.treats changes in order, count or keys
const treats = useStore(state => Object.keys(state.treats), shallow)

Fetching from multiple stores

Since you can create as many stores as you like, forwarding results to succeeding selectors is as natural as it gets.

const currentBear = useCredentialsStore(state => state.currentBear)
const bear = useBearStore(state => state.bears[currentBear])

Memoizing selectors

It is generally recommended to memoize selectors with useCallback. This will prevent unnecessary computations each render. It also allows React to optimize performance in concurrent mode.

const fruit = useStore(useCallback(state => state.fruits[id], [id]))

If a selector doesn't depend on scope, you can define it outside the render function to obtain a fixed reference without useCallback.

const selector = state => state.berries

function Component() {
  const berries = useStore(selector)

Overwriting state

The set function has a second argument, false by default. Instead of merging, it will replace the state model. Be careful not to wipe out parts you rely on, like actions.

import omit from "lodash-es/omit"

const useStore = create(set => ({
  salmon: 1,
  tuna: 2,
  deleteEverything: () => set({ }, true), // clears the entire store, actions included
  deleteTuna: () => set(state => omit(state, ['tuna']), true)
}))

Async actions

Just call set when you're ready, zustand doesn't care if your actions are async or not.

const useStore = create(set => ({
  fishies: {},
  fetch: async pond => {
    const response = await fetch(pond)
    set({ fishies: await response.json() })
  }
}))

Read from state in actions

set allows fn-updates set(state => result), but you still have access to state outside of it through get.

const useStore = create((set, get) => ({
  sound: "grunt",
  action: () => {
    const sound = get().sound
    // ...
  }
})

Reading/writing state and reacting to changes outside of components

Sometimes you need to access state in a non-reactive way, or act upon the store. For these cases the resulting hook has utility functions attached to its prototype.

const useStore = create(() => ({ paw: true, snout: true, fur: true }))

// Getting non-reactive fresh state
const paw = useStore.getState().paw
// Listening to all changes, fires on every change
const unsub1 = useStore.subscribe(console.log)
// Listening to selected changes, in this case when "paw" changes
const unsub2 = useStore.subscribe(console.log, state => state.paw)
// Subscribe also supports an optional equality function
const unsub3 = useStore.subscribe(console.log, state => [state.paw, state.fur], shallow)
// Subscribe also exposes the previous value
const unsub4 = useStore.subscribe((paw, previousPaw) => console.log(paw, previousPaw), state => state.paw)
// Updating state, will trigger listeners
useStore.setState({ paw: false })
// Unsubscribe listeners
unsub1()
unsub2()
unsub3()
unsub4()
// Destroying the store (removing all listeners)
useStore.destroy()

// You can of course use the hook as you always would
function Component() {
  const paw = useStore(state => state.paw)

Using zustand without React

Zustands core can be imported and used without the React dependency. The only difference is that the create function does not return a hook, but the api utilities.

import create from 'zustand/vanilla'

const store = create(() => ({ ... }))
const { getState, setState, subscribe, destroy } = store

You can even consume an existing vanilla store with React:

import create from 'zustand'
import vanillaStore from './vanillaStore'

const useStore = create(vanillaStore)

Transient updates (for often occuring state-changes)

The subscribe function allows components to bind to a state-portion without forcing re-render on changes. Best combine it with useEffect for automatic unsubscribe on unmount. This can make a drastic performance impact when you are allowed to mutate the view directly.

const useStore = create(set => ({ scratches: 0, ... }))

function Component() {
  // Fetch initial state
  const scratchRef = useRef(useStore.getState().scratches)
  // Connect to the store on mount, disconnect on unmount, catch state-changes in a reference
  useEffect(() => useStore.subscribe(
    scratches => (scratchRef.current = scratches), 
    state => state.scratches
  ), [])

Sick of reducers and changing nested state? Use Immer!

Reducing nested structures is tiresome. Have you tried immer?

import produce from 'immer'

const useStore = create(set => ({
  lush: { forest: { contains: { a: "bear" } } },
  set: fn => set(produce(fn)),
}))

const set = useStore(state => state.set)
set(state => {
  state.lush.forest.contains = null
})

Middleware

You can functionally compose your store any way you like.

// Log every time state is changed
const log = config => (set, get, api) => config(args => {
  console.log("  applying", args)
  set(args)
  console.log("  new state", get())
}, get, api)

// Turn the set method into an immer proxy
const immer = config => (set, get, api) => config(fn => set(produce(fn)), get, api)

const useStore = create(
  log(
    immer((set) => ({
      bees: false,
      setBees: (input) => set((state) => void (state.bees = input)),
    })),
  ),
)
How to pipe middlewares
import create from "zustand"
import produce from "immer"
import pipe from "ramda/es/pipe"

/* log and immer functions from previous example */
/* you can pipe as many middlewares as you want */
const createStore = pipe(log, immer, create)

const useStore = createStore(set => ({
  bears: 1,
  increasePopulation: () => set(state => ({ bears: state.bears + 1 }))
}))

export default useStore

For a TS example see the following discussion

How to type immer middleware in TypeScript
import { State, StateCreator } from 'zustand'
import produce, { Draft } from 'immer'

// Immer V8 or lower
const immer = <T extends State>(
  config: StateCreator<T, (fn: (draft: Draft<T>) => void) => void>
): StateCreator<T> => (set, get, api) =>
  config((fn) => set(produce(fn) as (state: T) => T), get, api)

// Immer V9
const immer = <T extends State>(
  config: StateCreator<T, (fn: (draft: Draft<T>) => void) => void>
): StateCreator<T> => (set, get, api) =>
  config((fn) => set(produce<T>(fn)), get, api)

Persist middleware

You can persist your store's data using any kind of storage.

import create from "zustand"
import { persist } from "zustand/middleware"

export const useStore = create(persist(
  (set, get) => ({
    fishes: 0,
    addAFish: () => set({ fish: get().fish + 1 })
  }),
  {
    name: "food-storage", // unique name
    getStorage: () => sessionStorage, // (optional) by default the 'localStorage' is used
  }
))

Can't live without redux-like reducers and action types?

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

const reducer = (state, { type, by = 1 }) => {
  switch (type) {
    case types.increase: return { grumpiness: state.grumpiness + by }
    case types.decrease: return { grumpiness: state.grumpiness - by }
  }
}

const useStore = create(set => ({
  grumpiness: 0,
  dispatch: args => set(state => reducer(state, args)),
}))

const dispatch = useStore(state => state.dispatch)
dispatch({ type: types.increase, by: 2 })

Or, just use our redux-middleware. It wires up your main-reducer, sets initial state, and adds a dispatch function to the state itself and the vanilla api. Try this example.

import { redux } from 'zustand/middleware'

const useStore = create(redux(reducer, initialState))

Calling actions outside a React event handler

Because React handles setState synchronously if it's called outside an event handler. Updating the state outside an event handler will force react to update the components synchronously, therefore adding the risk of encountering the zombie-child effect. In order to fix this, the action needs to be wrapped in unstable_batchedUpdates

import { unstable_batchedUpdates } from 'react-dom' // or 'react-native'

const useStore = create((set) => ({
  fishes: 0,
  increaseFishes: () => set((prev) => ({ fishes: prev.fishes + 1 }))
}))

const nonReactCallback = () => {
  unstable_batchedUpdates(() => {
    useStore.getState().increaseFishes()
  })
}

More details: https://github.com/pmndrs/zustand/issues/302

Redux devtools

import { devtools } from 'zustand/middleware'

// Usage with a plain action store, it will log actions as "setState"
const useStore = create(devtools(store))
// Usage with a redux store, it will log full action types
const useStore = create(devtools(redux(reducer, initialState)))

devtools takes the store function as its first argument, optionally you can name the store with a second argument: devtools(store, "MyStore"), which will be prefixed to your actions.

TypeScript

type State = {
  bears: number
  increase: (by: number) => void
}

const useStore = create<State>(set => ({
  bears: 0,
  increase: (by) => set(state => ({ bears: state.bears + by })),
}))

You can also use an interface:

import { State } from 'zustand';

interface BearState extends State {
  bears: number
  increase: (by: number) => void
}

Or, use combine and let tsc infer types.

import { combine } from 'zustand/middleware'

const useStore = create(
  combine(
    { bears: 0 }, 
    (set) => ({ increase: (by: number) => set((state) => ({ bears: state.bears + by })) })
  ),
)

Testing

For information regarding testing with Zustand, visit the dedicated Wiki page.

Comments
  • SSR Example (SSR data is shared)

    SSR Example (SSR data is shared)

    I'm using Next.js and have a separate file state.js that has something like this:

    export const useSessionStore = create(combine({
      session: {},
    }, set => ({
      setSession: (session) => set({ session }),
    })))
    

    And then calling setSession() on the server (for example in _app.js) after a successful login. When reading session on the server + client, it seems to work fine. So far so good.

    The problem is: the session seems to be saved in Node.js memory and shared with everyone(?). When you login on one browser, the same session data is returned when you load the page on another browser. So I'm assuming when I set session on the server, it persists on Node.js side and returns the same session for all clients.

    What am I doing wrong, or is zustand not meant for this?

    help wanted 
    opened by jd327 90
  • breaking(types): Add higher kinded mutator types

    breaking(types): Add higher kinded mutator types

    Okay @dai-shi now you have two options:

    A. This PR (not complete yet) Makes the change as minimal as possible, just adds the types proposed in #710, zero change in runtime code.

    B. #662 Not only adds #710 but also rewrites the whole codebase to drastically increase the code quality. Don't mind me but the current code is quite a mess, I like to write code for fun so I thought let's rewrite this whole thing nicely. Now this obviously will produce relatively large and unhelpful diffs, nothing can be done about that. It would be much easier to review if you compare the files locally without the red-green diff. But now I have a small condition: I'll remove prettier and some lint rules, but don't worry you can add them back but you'll have to do it yourself (you have the edit rights). Consider this a little treat that I'm giving myself :P I hope you won't mind.

    Let me know which of the two options you prefer. If you think increasing the code quality is worth taking the pain to review, I'd suggest you go with the second option. I don't mind whichever you pick.

    opened by devanshj 68
  • Different behaviour of LocalStorage and AsyncStorage

    Different behaviour of LocalStorage and AsyncStorage

    In my app, I'm using @react-native-async-storage/async-storage because I plan to support React Native. But because React Native is not expected to be supported soon, I decided to switch back to LocalStorage and my app stopped working. If I will add setTimeout to state.dispatchStoreRehydrated();, it works. It's probably because LocalStorage is sync while AsyncStorage isn't.

    onRehydrateStorage: () => (state) => {
      if (state)
        // Fix for LocalStorage. With AsyncStorage, setTimeout
        // is not required.
        setTimeout(() => {
          state.dispatchStoreRehydrated();
        }, 0);
    },
    
    middleware/persist 
    opened by steida 35
  • fix(build): Improved ESM support for most used bundlers with fallbacks for older bundlers

    fix(build): Improved ESM support for most used bundlers with fallbacks for older bundlers

    commit description

    separates esm and cjs to different dist folders
    forced types of the folder to support other rollup instances
    the separation was made to support maximum bundlers , though
    the milage may way vary based on the ESM implementation of your
    bundler
    

    Why ?

    There's a mismatch in implementation when it comes to esModuleInterop between the bundlers primarily rollup and webpack , thus causing issues when generating hybrid module libraries. The following commit is needed to address #454 where webpack fails to detect the esm files this is because webpack depends on the package to be strictly forced to be "type":"module" or have .mjs files.

    Changes

    • Modifies rollup.config.js to direct the built assets into different folders
    • Modifies package.json#copy script to handle the strict "type":"module" for the esm folder and "type":"commonjs" on the main package.json

    Additional Notes Please do not merge this unless both bundlers confirm the esm and cjs modules to be working properly, I'll be reporting the tests of both in a few minutes.

    Let me know if something needs to be changed.

    opened by barelyhuman 34
  • Allow persist middleware to accept 'localStorage' and 'sessionStorage' for easier usage of session

    Allow persist middleware to accept 'localStorage' and 'sessionStorage' for easier usage of session

    Hi there @AnatoleLucet and @dai-shi !

    After the middleware localStorage PR was closed I quickly ran into the situation where we actually wanted to persist state in session. I can imagine though that most developers wouldn't actually want this as the store persist in memory most of the time - but in our specific case we have multiple front-ends hosted on the same domain and the user would switch between them on multiple occasions in the same session, where we actually wanted to get back the stored data when they would come back to our frontend where the Zustand store was initially created.

    Of course it's possible to pass window.sessionStorage, but you are left doing the same check that initially had to be done for localStorage in order to make it work in SSR. Allowing the user to pass 'localStorage' and 'sessionStorage' as string options and retrieving the apis from the window if it's defined solves it - but not sure if this is a welcome change since @dai-shi actually preferred not checking window.

    Let me know what you think

    opened by RobbyUitbeijerse 34
  • Importing in a `type=module` project fails

    Importing in a `type=module` project fails

    First: thanks for the simplified version of state management. So glad I found it, so sad it took me so long ;).

    I created a small project, where the package.json sets it to be a ESM project, by type=module. See https://codeberg.org/wolframkriesing/bug-exploration-zustand-and-esm/src/branch/main/package.json#L4

    I ran into two issues, that are somehow related to #201 but I am not sure exactly what's the root cause.

    The Problem(s)

    I wanted to get zustand to be testable with mocha in an ESM setup. But I ran into:

    1. When using type=module and importing zustand/vanilla mocha says there is no such file. No idea what that might be. This is the JS file and the error it throws: https://codeberg.org/wolframkriesing/bug-exploration-zustand-and-esm/src/branch/main/src/vanilla.test.js
    2. When importing zustand/vanilla.js the default export is somehow broken. A change of exports.default = create;
      to
      module.exports = create;
      in zustand/vanilla.js would fix it. This sounds like a packager problem in zustand? https://codeberg.org/wolframkriesing/bug-exploration-zustand-and-esm/src/branch/main/src/vanilla-js.test.js

    Is the ESM setup just not there yet, and not recommended? I had hoped to go there gradually. How do others solve this issue?

    opened by wolframkriesing 33
  • Rewrite with better types

    Rewrite with better types

    (Background) I want to know if yall are interested in me doing a rewrite, it'll improve the user-facing types as well as internal types & code. If yes, I'll first do a free rewrite -- ie without caring about backwards-compatibility, standards, opinions, naming, etc -- then once that's done we'll worry about the other things. You can keep as much code as you want.

    Till now I've rewritten zustand/vanilla (feel free to ask questions, I'll document some things later). As I continue to rewrite I'll understand what the runtime behavior is (because I haven't used zustand) and hence I'll type accordingly, so it won't be an incremental change, I might change the existing types if required.

    Bug fixes till now:

    1. Bug (as seen on twitter). Fixed.
    2. Bug (as seen on twitter). Fixed.

    New features till now: (well they are kinda bugs :P)

    1. If replace flag is set, you'll have to provide the state type not the partial of state type. Before. After.

    Progress:

    • [x] zustand/vanilla
    • [x] zustand/react
    • [x] zustand/shallow
    • [x] zustand/context
    • [x] zustand/middlewares/
      • [x] zustand/middlewares/persist
      • [x] zustand/middlewares/combine
      • [x] zustand/middlewares/subscribeWithSelector
      • [x] zustand/middlewares/devtools
      • [x] zustand/middlewares/redux

    Miscellaneous: The original version uses some trick (which I've not read yet) to disallow { count: undefined } (but allow {}). The new types would disallow { count: undefined } only when --exactOptionalPropertyTypes flag is set. I might revert back to original, or use some other trick.

    cc @dai-shi

    opened by devanshj 30
  • [Question] Creating slices using Typescript

    [Question] Creating slices using Typescript

    opened by KeeganFargher 30
  • Migrating Async/Await to Promise

    Migrating Async/Await to Promise

    WIP

    middleware.ts is completely migrated from Async/Await to Promise. and also sync apis will be called in a sync manner.

    • [x] a general API created to handle both sync/async peacefully
    • [x] async tests passed
    • [x] sync tests added
    • [x] sync test passed
    • [x] types added

    fixing #346

    opened by TheEhsanSarshar 30
  • Zustand 2.x // Ensure order of subscribers

    Zustand 2.x // Ensure order of subscribers

    This could be a fix for #64.

    The original issue was due to the current behavior of useEffect. It seems effects in child components are called before parent effects. We subscribe to the store in useEffect so child listeners were added to the array before parent listeners. I changed it so the enumeration order should always match the render order. Now child listeners will be removed before they can be called if the render is synchronous.

    One thing to note, ~we're adding a key to a mutable object during React's render phase~. Edit: I've removed the need for mutating an object.

    opened by JeremyRH 29
  • TS issue with the set function when using devtools (with older TS versions)

    TS issue with the set function when using devtools (with older TS versions)

    Hey there zustand team

    I'm having a problem when using zustand with devtools in my next.js project.

    When running the store locally, everything works fine and I'm seeing devtools. Awesome.

    But, when building my app for production with nx/next.js, it throws the following error:

    Type error: Expected 3-4 arguments, but got 1.
    
      62 |       damageLocation: TDamageLocation
      63 |     ) => {
    > 64 |       set({ damageType, damageLocation, view: 'station' });
         |       ^
      65 |     },
      66 |     updateStation: (station: IStationState) => {
      67 |       set({ station, view: 'timeSlot' });
    

    What have I do so far:

    1. Tried to follow this https://github.com/pmndrs/zustand/discussions/976 and looked at the tests/middlewareTypes.test.tsx and tests/devtools.test.tsx examples but not successful.
    2. Tried to type the store like in the example above: create<InitialState, [["zustand/devtools", InitialState]]>
    3. Tried changing the set function called on line 64 (example above) but then I get the same error on a different function

    Using the following core dependencies:

    • next: 12.1.0,
    • nx: 13.9.5,
    • react: 17.0.2,
    • zustand: ^4.0.0-rc.1

    Let me know if you need more details or if this makes no sense.

    opened by kwaimind 28
  • fix(middleware/persist): hydrate in sync (new impl with storage option)

    fix(middleware/persist): hydrate in sync (new impl with storage option)

    Related Issues

    Fixes #1517.

    Summary

    In #1463, I hoped to avoid toThenable() whose implementation is complicated, and used Promise.resolve() instead. I wasn't aware this is a regression because it didn't migrate the tests.

    This PR fixes the tests, and use toThenable.

    Check List

    • [ ] yarn run prettier for formatting code and docs
    opened by dai-shi 2
  • bug(middleware/persist): using new storage option with createJSONStorage causes subscription to fire early (regression)

    bug(middleware/persist): using new storage option with createJSONStorage causes subscription to fire early (regression)

    Summary

    using old getStorage option would not fire subscriptions when retrieving the state from storage for the first time, but storage does

    Link to reproduction

    old: https://codesandbox.io/s/autumn-fog-400vf4 new: https://codesandbox.io/s/happy-carson-0teelt

    Check List

    • [x] I've already opened a discussion before opening this issue.
    opened by meypod 0
  • doc: update documentation of persist

    doc: update documentation of persist

    Related Issues

    Fixes #1510

    Summary

    Update doc to include how to handle Map and Set with the new persist API.

    issue since i have yarn v3 installed, it creates .yarn and .yarnrc.yml and need me to set pacakge to v1 with yarn set version classic so not sure i can run prettier easily but i will run it and delete the files we don't want commited.

    Check List

    • [x] yarn run prettier for formatting code and docs
    opened by wcastand 1
  • Mocking state broken in 4.2.0 (with AsyncStorage in React Native)

    Mocking state broken in 4.2.0 (with AsyncStorage in React Native)

    Summary

    Hello and thank you for a great state library!

    When upgrading to 4.2.0 and using persist, the suggested mock approach throws error TypeError: Cannot read properties of undefined (reading 'getItem')

    Suggested mock code that breaks:

    // when creating a store, we get its initial state, create a reset function and add it in the set
    const create =
      () =>
      <S>(createState: StateCreator<S>) => {
        const store = actualCreate<S>(createState); // <-- breaks here
        const initialState = store.getState();
        storeResetFns.add(() => store.setState(initialState, true));
        return store;
      };
    

    Our persist setup:

    import create from 'zustand';
    import {createJSONStorage, persist} from 'zustand/middleware';
    import AsyncStorage from '@react-native-async-storage/async-storage';
    ...
    const useAppState = create<State & Actions>()(
      persist(
        set => ({
          ...initialState,
          setIsColdStarted: isColdStarted => set({isColdStarted}),
          setSettings: settings =>
            set(state => ({settings: {...state.settings, ...settings}})),
          reset: () => set(initialState),
        }),
        {
          name: 'appState',
          storage: createJSONStorage(() => AsyncStorage), // <-- instead of deprecated getStorage: () => AsyncStorage
          partialize: ({settings}) => ({
            settings,
          }),
        },
      ),
    );
    
    help wanted 
    opened by swemail 19
  • Add Slices pattern example

    Add Slices pattern example

    By ading this example we can combine the real Slices pattern implementation (instead of multiple stores) with the resetAll method. Hope this helps! ๐Ÿ˜„

    Related Issues

    Fixes #.

    Summary

    Check List

    • [ ] yarn run prettier for formatting code and docs
    opened by jmantonellini 2
Releases(v4.2.0)
  • v4.2.0(Jan 1, 2023)

    This version adds some new features in middleware.

    What's Changed

    • feat(middleware/devtools): Better redux devtools. One connection for all zustand stores by @pavlobu in https://github.com/pmndrs/zustand/pull/1435
    • feat(middleware/persist): new storage option by @dai-shi in https://github.com/pmndrs/zustand/pull/1463
    • fix(build): disable esModule and re-export for nodejs by @barelyhuman in https://github.com/pmndrs/zustand/pull/1486

    New Contributors

    • @Guchii made their first contribution in https://github.com/pmndrs/zustand/pull/1476
    • @sewera made their first contribution in https://github.com/pmndrs/zustand/pull/1478
    • @pavlobu made their first contribution in https://github.com/pmndrs/zustand/pull/1435

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.1.5...v4.2.0

    Source code(tar.gz)
    Source code(zip)
  • v4.1.5(Dec 5, 2022)

    This version has several small improvements.

    What's Changed

    • fix(middleware/devtools): do not use optional catch binding syntax by @mskrzypek in https://github.com/pmndrs/zustand/pull/1431
    • feat(shallow): Add support of Maps and Sets to shallow comparator by @anton-lunev in https://github.com/pmndrs/zustand/pull/1451
    • refactor(vanilla/types): replace hardcoded types with StoreApi type by @Arsikod in https://github.com/pmndrs/zustand/pull/1459
    • Fix: Programmatic module.exports addition for named and default exports in CJS by @barelyhuman in https://github.com/pmndrs/zustand/pull/1460

    New Contributors

    • @wmcb91 made their first contribution in https://github.com/pmndrs/zustand/pull/1398
    • @chrisvander made their first contribution in https://github.com/pmndrs/zustand/pull/1426
    • @boatilus made their first contribution in https://github.com/pmndrs/zustand/pull/1428
    • @chybisov made their first contribution in https://github.com/pmndrs/zustand/pull/1453
    • @hicucu made their first contribution in https://github.com/pmndrs/zustand/pull/1438
    • @mskrzypek made their first contribution in https://github.com/pmndrs/zustand/pull/1431
    • @anton-lunev made their first contribution in https://github.com/pmndrs/zustand/pull/1451
    • @Arsikod made their first contribution in https://github.com/pmndrs/zustand/pull/1459

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.1.4...v4.1.5

    Source code(tar.gz)
    Source code(zip)
  • v4.1.4(Oct 31, 2022)

    This should improve some importing problems. Uncertain if it fixes everything.

    What's Changed

    • fix(build): use *.d.mts for esm ('import' condition only) by @dai-shi in https://github.com/pmndrs/zustand/pull/1387
    • fix(build): no import.meta for "module" condition by @dai-shi in https://github.com/pmndrs/zustand/pull/1393

    New Contributors

    • @guenyoo made their first contribution in https://github.com/pmndrs/zustand/pull/1388

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.1.3...v4.1.4

    Source code(tar.gz)
    Source code(zip)
  • v4.1.3(Oct 23, 2022)

    This improves store types for TS users. We also upgrade rollup. Please report issues if anyone finds any.

    What's Changed

    • fix(types): assume getState and setState will always exist on the store by @devanshj in https://github.com/pmndrs/zustand/pull/1371
    • fix(types): fix StateCreator subtyping by @devanshj in https://github.com/pmndrs/zustand/pull/1373

    New Contributors

    • @dongkun made their first contribution in https://github.com/pmndrs/zustand/pull/1352
    • @srini-leanfolks made their first contribution in https://github.com/pmndrs/zustand/pull/1357

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.1.2...v4.1.3

    Source code(tar.gz)
    Source code(zip)
  • v4.1.2(Oct 9, 2022)

    This includes some fixes for edge cases. Most notably, supporting old TypeScript versions.

    What's Changed

    • fix(context): store property missing from useStoreApi by @exuanbo in https://github.com/pmndrs/zustand/pull/1258
    • fix: should use Object.is to compare two value by @hchlq in https://github.com/pmndrs/zustand/pull/1314
    • Rewrite TakeTwo, SkipTwo and Mutate to make them work for older ts versions too by @devanshj in https://github.com/pmndrs/zustand/pull/1348

    New Contributors

    • @chrisk-7777 made their first contribution in https://github.com/pmndrs/zustand/pull/1222
    • @timarney made their first contribution in https://github.com/pmndrs/zustand/pull/1223
    • @radaelilucca made their first contribution in https://github.com/pmndrs/zustand/pull/1230
    • @Exalted100 made their first contribution in https://github.com/pmndrs/zustand/pull/1231
    • @dbritto-dev made their first contribution in https://github.com/pmndrs/zustand/pull/1236
    • @guymoon made their first contribution in https://github.com/pmndrs/zustand/pull/1267
    • @Cuppachino made their first contribution in https://github.com/pmndrs/zustand/pull/1291
    • @mugi-uno made their first contribution in https://github.com/pmndrs/zustand/pull/1303
    • @hchlq made their first contribution in https://github.com/pmndrs/zustand/pull/1315
    • @DiemasMichiels made their first contribution in https://github.com/pmndrs/zustand/pull/1325
    • @FKSI made their first contribution in https://github.com/pmndrs/zustand/pull/1326
    • @Rec0iL99 made their first contribution in https://github.com/pmndrs/zustand/pull/1344
    • @kpue made their first contribution in https://github.com/pmndrs/zustand/pull/1346
    • @exuanbo made their first contribution in https://github.com/pmndrs/zustand/pull/1258

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.1.1...v4.1.2

    Source code(tar.gz)
    Source code(zip)
  • v4.1.1(Aug 22, 2022)

    In v4.1.0, there are some TypeScript type issues in redux and devtools middleware, which should be fixed.

    What's Changed

    • fix(middleware): revert types of redux middleware by @dai-shi in https://github.com/pmndrs/zustand/pull/1206
    • fix(types)(middleware/devtools): copy devtools option types instead of importing by @dai-shi in https://github.com/pmndrs/zustand/pull/1207
    • refactor(types): prefer using import type by @dai-shi in https://github.com/pmndrs/zustand/pull/1208

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.1.0...v4.1.1

    Source code(tar.gz)
    Source code(zip)
  • v4.1.0(Aug 18, 2022)

    This supports non-object state. It's probably one of the biggest changes in API design throughout the zustand development history. But, probably 99.9% of users won't use it ๐Ÿ˜ .

    What's Changed

    • fix(types)(middleware/devtools): fix action type in devtools's setState by @lucasrabiec in https://github.com/pmndrs/zustand/pull/1183
    • feat(vanilla): non-object state by @dai-shi in https://github.com/pmndrs/zustand/pull/1144
    • fix(types)(middleware): use official Config type for options by @dai-shi in https://github.com/pmndrs/zustand/pull/1200
    • fix(types): typo in jsdoc and follow-up #1144 by @devanshj in https://github.com/pmndrs/zustand/pull/1199

    New Contributors

    • @garrett-hopper made their first contribution in https://github.com/pmndrs/zustand/pull/1152
    • @satvikpendem made their first contribution in https://github.com/pmndrs/zustand/pull/1163
    • @markroze made their first contribution in https://github.com/pmndrs/zustand/pull/1188
    • @lucasrabiec made their first contribution in https://github.com/pmndrs/zustand/pull/1184
    • @spenceradolph made their first contribution in https://github.com/pmndrs/zustand/pull/1193

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.0.0...v4.1.0

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(Jul 26, 2022)

    ๐ŸŽ‰ ๐ŸŽ‰ ๐ŸŽ‰ Zustand v4 is here ๐ŸŽ‰ ๐ŸŽ‰ ๐ŸŽ‰

    Backward compatible with v3 in JS

    v4 API is completely backward compatible, so it's just nothing to update if you are JS users.

    One note is v4 depends on use-sync-external-store. There might be some bundling issues. Please report them if you encounter such cases.

    TypeScript types are rewritten

    To better support types with middleware, v4 TypeScript code is rewritten. Please find docs/typescript.md for more information.

    New API for context usage

    In v3, zustand/context is provided as a workaround. v4 API exposes createStore and useStore, which are more flexible. Please read this for usage. If you are unsure about the usage, open a new discussion.

    Counter example: https://codesandbox.io/s/polished-pond-4jn1e2

    Deprecated APIs are removed

    Some APIs are already deprecated in v3, and they are removed in v4. Please make sure to update to the latest version of v3 before migrating to v4.

    What's Changed

    • breaking(vanilla): drop deprecated store.subscribe with selector by @dai-shi in https://github.com/pmndrs/zustand/pull/604
    • breaking(middleware): drop deprecated persist options and make removeItem required by @dai-shi in https://github.com/pmndrs/zustand/pull/598
    • breaking(core): drop v2 hook compatibility by @dai-shi in https://github.com/pmndrs/zustand/pull/597
    • breaking(types): drop deprecated UseStore type by @dai-shi in https://github.com/pmndrs/zustand/pull/596
    • feat: use-sync-external-store by @dai-shi in https://github.com/pmndrs/zustand/pull/550
    • breaking(middleware/devtools): use official devtools extension types by @dai-shi in https://github.com/pmndrs/zustand/pull/819
    • breaking(middleware/devtools): remove deprecations and warnings by @devanshj in https://github.com/pmndrs/zustand/pull/892
    • fix(build): separate vanilla build by @dai-shi in https://github.com/pmndrs/zustand/pull/904
    • breaking(types): Add higher kinded mutator types by @devanshj in https://github.com/pmndrs/zustand/pull/725
    • fix(index): export createStore from vanilla by @dai-shi in https://github.com/pmndrs/zustand/pull/914
    • fix(middleware): separate immer middleware by @dai-shi in https://github.com/pmndrs/zustand/pull/915
    • fix(middleware/devtools): add enabled option and show devtools warning only if enabled by @Aslemammad in https://github.com/pmndrs/zustand/pull/880
    • breaking(middleware/devtools): remove checking old string option by @dai-shi in https://github.com/pmndrs/zustand/pull/933
    • Fix TS4023 and other minor changes by @devanshj in https://github.com/pmndrs/zustand/pull/940
    • fix(types): avoid any in react.ts by @dai-shi in https://github.com/pmndrs/zustand/pull/941
    • fix(build): add downlevel-dts by @dai-shi in https://github.com/pmndrs/zustand/pull/1005
    • refactor: prefer interfaces by @dai-shi in https://github.com/pmndrs/zustand/pull/1012
    • fix(types): Mark more methods bivariant by @RyanCavanaugh in https://github.com/pmndrs/zustand/pull/1029
    • fix(types): remove Partial typo from persist by @devanshj in https://github.com/pmndrs/zustand/pull/1051
    • fix(shallow): restrict types by @dai-shi in https://github.com/pmndrs/zustand/pull/1070
    • feature(persist): add method getOptions on persist api and update documentation by @tbor00 in https://github.com/pmndrs/zustand/pull/1075
    • feat(types): minimize types by deprecating them by @devanshj in https://github.com/pmndrs/zustand/pull/1089
    • fix(build): a workaround for ESM for use-sync-external-store by @dai-shi in https://github.com/pmndrs/zustand/pull/953
    • fix(types): use TS interfaces only for public api by @dai-shi in https://github.com/pmndrs/zustand/pull/1106
    • fix(shallow): types with useStore by @dai-shi in https://github.com/pmndrs/zustand/pull/1108
    • fix(shallow): types with useStore again by @dai-shi in https://github.com/pmndrs/zustand/pull/1117
    • refactor(types): avoid using deprecated types by @dai-shi in https://github.com/pmndrs/zustand/pull/1122

    New Contributors

    • @piotr-cz made their first contribution in https://github.com/pmndrs/zustand/pull/927
    • @mahendradambe made their first contribution in https://github.com/pmndrs/zustand/pull/956
    • @Himself65 made their first contribution in https://github.com/pmndrs/zustand/pull/978
    • @jenglamlow made their first contribution in https://github.com/pmndrs/zustand/pull/988
    • @InfiniteXyy made their first contribution in https://github.com/pmndrs/zustand/pull/1006
    • @guilleon-velasco made their first contribution in https://github.com/pmndrs/zustand/pull/1009
    • @sepehr-safari made their first contribution in https://github.com/pmndrs/zustand/pull/1049
    • @rnike made their first contribution in https://github.com/pmndrs/zustand/pull/1056
    • @tbor00 made their first contribution in https://github.com/pmndrs/zustand/pull/1071
    • @Carnageous made their first contribution in https://github.com/pmndrs/zustand/pull/1057
    • @xlboy made their first contribution in https://github.com/pmndrs/zustand/pull/1082
    • @RyanCavanaugh made their first contribution in https://github.com/pmndrs/zustand/pull/1029
    • @Gabriel-Alves-Cunha made their first contribution in https://github.com/pmndrs/zustand/pull/997
    • @chann44 made their first contribution in https://github.com/pmndrs/zustand/pull/1016

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.7.2...v4.0.0

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-rc.4(Jul 20, 2022)

    There was still a tiny issue with typing in zustand/shallow, and it's finally fixed.

    What's Changed

    • fix(shallow): types with useStore again by @dai-shi in https://github.com/pmndrs/zustand/pull/1117
    • refactor(types): avoid using deprecated types by @dai-shi in https://github.com/pmndrs/zustand/pull/1122

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.0.0-rc.3...v4.0.0-rc.4

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-rc.3(Jul 19, 2022)

    v4.0.0-rc.2 has some issues with TypeScript typing which should be fixed in this version.

    What's Changed

    • fix(types): use TS interfaces only for public api by @dai-shi in https://github.com/pmndrs/zustand/pull/1106
    • fix(shallow): types with useStore by @dai-shi in https://github.com/pmndrs/zustand/pull/1108

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.0.0-rc.2...v4.0.0-rc.3

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-rc.2(Jul 17, 2022)

    We've made some changes in TypeScript types. We believe what's remaining is basically docs issues. Please feel free to open issues/discussions.

    What's Changed

    • fix(types): Mark more methods bivariant by @RyanCavanaugh in https://github.com/pmndrs/zustand/pull/1029
    • fix(types): remove Partial typo from persist by @devanshj in https://github.com/pmndrs/zustand/pull/1051
    • fix(shallow): restrict types by @dai-shi in https://github.com/pmndrs/zustand/pull/1070
    • feature(persist): add method getOptions on persist api and update documentation by @tbor00 in https://github.com/pmndrs/zustand/pull/1075
    • feat(types): minimize types by deprecating them by @devanshj in https://github.com/pmndrs/zustand/pull/1089
    • fix(build): a workaround for ESM for use-sync-external-store by @dai-shi in https://github.com/pmndrs/zustand/pull/953

    New Contributors

    • @mahendradambe made their first contribution in https://github.com/pmndrs/zustand/pull/956
    • @Himself65 made their first contribution in https://github.com/pmndrs/zustand/pull/978
    • @jenglamlow made their first contribution in https://github.com/pmndrs/zustand/pull/988
    • @InfiniteXyy made their first contribution in https://github.com/pmndrs/zustand/pull/1006
    • @guilleon-velasco made their first contribution in https://github.com/pmndrs/zustand/pull/1009
    • @sepehr-safari made their first contribution in https://github.com/pmndrs/zustand/pull/1049
    • @rnike made their first contribution in https://github.com/pmndrs/zustand/pull/1056
    • @tbor00 made their first contribution in https://github.com/pmndrs/zustand/pull/1071
    • @Carnageous made their first contribution in https://github.com/pmndrs/zustand/pull/1057
    • @xlboy made their first contribution in https://github.com/pmndrs/zustand/pull/1082
    • @RyanCavanaugh made their first contribution in https://github.com/pmndrs/zustand/pull/1029

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.0.0-rc.1...v4.0.0-rc.2

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-rc.1(Apr 29, 2022)

    This improves some types for TypeScript users. Please read ./docs for TypeScript usage and v4 migration.

    What's Changed

    • breaking(middleware/devtools): remove checking old string option by @dai-shi in https://github.com/pmndrs/zustand/pull/933
    • Fix TS4023 and other minor changes by @devanshj in https://github.com/pmndrs/zustand/pull/940
    • fix(types): avoid any in react.ts by @dai-shi in https://github.com/pmndrs/zustand/pull/941

    New Contributors

    • @piotr-cz made their first contribution in https://github.com/pmndrs/zustand/pull/927

    Full Changelog: https://github.com/pmndrs/zustand/compare/v4.0.0-rc.0...v4.0.0-rc.1

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-rc.0(Apr 18, 2022)

    Long-awaited zustand v4!

    We started working on #550 at Aug 31 2021. It's been more than 7 months!

    Release status

    Although this release is v4.0.0-rc.0, we treat this as a normal release. While we might make some changes before the final one, the stability of this release should be same as other releases like v3.7.*.

    No breaking changes in JavaScript API

    Most notably, this release is backward compatible with the latest v3 API. Some features deprecated in v3 are removed in v4. It's highly recommended to update to latest v3, before upgrading to v4, and check any deprecation messages.

    Big rewrite in TypeScript

    Zustand code in JS is surprisingly small, and its value is actually in TypeScript. Although it is very tricky to support mutation nature of zustand middleware, @devanshj did a great job to support types as much as possible. There are some breaking changes in types from v3. Please refer ./docs/typescript.md and ./docs/v4-migration.md.

    Your feedback is necessary

    As always, feedback is welcome, and even necessary this time because otherwise nothing happens. Please try v4 and open issues and discussions (discussions are preferable if you are not sure which).

    What's Changed

    • breaking(vanilla): drop deprecated store.subscribe with selector by @dai-shi in https://github.com/pmndrs/zustand/pull/604
    • breaking(middleware): drop deprecated persist options and make removeItem required by @dai-shi in https://github.com/pmndrs/zustand/pull/598
    • breaking(core): drop v2 hook compatibility by @dai-shi in https://github.com/pmndrs/zustand/pull/597
    • breaking(types): drop deprecated UseStore type by @dai-shi in https://github.com/pmndrs/zustand/pull/596
    • feat: use-sync-external-store by @dai-shi in https://github.com/pmndrs/zustand/pull/550
    • breaking(middleware/devtools): use official devtools extension types by @dai-shi in https://github.com/pmndrs/zustand/pull/819
    • breaking(middleware/devtools): remove deprecations and warnings by @devanshj in https://github.com/pmndrs/zustand/pull/892
    • fix(build): separate vanilla build by @dai-shi in https://github.com/pmndrs/zustand/pull/904
    • breaking(types): Add higher kinded mutator types by @devanshj in https://github.com/pmndrs/zustand/pull/725
    • fix(index): export createStore from vanilla by @dai-shi in https://github.com/pmndrs/zustand/pull/914
    • fix(middleware): separate immer middleware by @dai-shi in https://github.com/pmndrs/zustand/pull/915
    • fix(middleware/devtools): add enabled option and show devtools warning only if enabled by @Aslemammad in https://github.com/pmndrs/zustand/pull/880

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.7.2...v4.0.0-rc.0

    Source code(tar.gz)
    Source code(zip)
  • v3.7.2(Apr 7, 2022)

    This fixes an issue in persist for some use cases.

    What's Changed

    • fix(middleware/persist): Merge storage value with the latest store state by @zerofirework in https://github.com/pmndrs/zustand/pull/894

    New Contributors

    • @disambiguator made their first contribution in https://github.com/pmndrs/zustand/pull/876
    • @zerofirework made their first contribution in https://github.com/pmndrs/zustand/pull/894

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.7.1...v3.7.2

    Source code(tar.gz)
    Source code(zip)
  • v3.7.1(Feb 28, 2022)

    This fixes a type issue with zustand/context in v3.7.0.

    What's Changed

    • fix(context): revert removing overloads in UseContextStore by @devanshj in https://github.com/pmndrs/zustand/pull/817
    • fix(middleware/devtools): deprecate serialize.options by @dai-shi in https://github.com/pmndrs/zustand/pull/828

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.7.0...v3.7.1

    Source code(tar.gz)
    Source code(zip)
  • v3.7.0(Feb 10, 2022)

    This release is to prepare for v4 release, which will include some breaking changes. Especially typing store with middleware will be changed. This release gives partial migration path (see tests/middlewareTypes.test.tsx for examples), so it's highly recommended to try this version before v4 comes and report issues.

    It also fixes some small typing issues and improves UMD/SystemJS bundling. Oh, and last but not least, vite users don't need to set NODE_ENV anymore.

    What's Changed

    • fix(devtools): don't show jsdoc deprecation warning when no options are passed by @devanshj in https://github.com/pmndrs/zustand/pull/781
    • fix(middleware): match vanilla StateCreator type in subscribeWithSelector by @toddw in https://github.com/pmndrs/zustand/pull/787
    • feat(build): use __DEV__ to control development mode by @dai-shi in https://github.com/pmndrs/zustand/pull/789
    • feat: Migrations regarding higher kinded mutators for v4 by @devanshj in https://github.com/pmndrs/zustand/pull/772

    New Contributors

    • @DanielPower made their first contribution in https://github.com/pmndrs/zustand/pull/751
    • @toddw made their first contribution in https://github.com/pmndrs/zustand/pull/787

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.9...v3.7.0

    Source code(tar.gz)
    Source code(zip)
  • v3.6.9(Jan 10, 2022)

    This adds UMD and SystemJS builds for CDN.

    What's Changed

    • fix(build): Generate umd and system files by @romulo94 in https://github.com/pmndrs/zustand/pull/740

    New Contributors

    • @romulo94 made their first contribution in https://github.com/pmndrs/zustand/pull/740

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.8...v3.6.9

    Source code(tar.gz)
    Source code(zip)
  • v3.6.8(Dec 24, 2021)

    This fixes some issues in devtools middleware.

    What's Changed

    • fix(middleware/devtools): minor fixes for pause recording feature by @devanshj in https://github.com/pmndrs/zustand/pull/720
    • fix(middleware/devtools): revert extension connector with try-catch to fix RN usage by @dai-shi in https://github.com/pmndrs/zustand/pull/724
    • fix(middleware/devtools): deprecate passing name directly instead of an object by @devanshj in https://github.com/pmndrs/zustand/pull/731

    New Contributors

    • @skuteli made their first contribution in https://github.com/pmndrs/zustand/pull/718
    • @omidantilong made their first contribution in https://github.com/pmndrs/zustand/pull/712

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.7...v3.6.8

    Source code(tar.gz)
    Source code(zip)
  • v3.6.7(Dec 7, 2021)

    There was a regression in devtools middleware in v3.6.6, which is fixed.

    What's Changed

    • fix(middleware): devtools work in non-browser by @dai-shi in https://github.com/pmndrs/zustand/pull/693

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.6...v3.6.7

    Source code(tar.gz)
    Source code(zip)
  • v3.6.6(Dec 3, 2021)

    This fixes and improves devtools middleware. The basic usage shouldn't be changed. If you have questions on usage, please open a new discussion.

    What's Changed

    • refactor(core): extract react.ts from index.ts by @dai-shi in https://github.com/pmndrs/zustand/pull/663
    • refactor(middleware): split into multiple files by @dai-shi in https://github.com/pmndrs/zustand/pull/664
    • rewrite devtools by @devanshj in https://github.com/pmndrs/zustand/pull/675

    New Contributors

    • @Thisen made their first contribution in https://github.com/pmndrs/zustand/pull/688
    • @devanshj made their first contribution in https://github.com/pmndrs/zustand/pull/675

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.5...v3.6.6

    Source code(tar.gz)
    Source code(zip)
  • v3.6.5(Nov 9, 2021)

    This version further improves to fix some typing issues introduced in v3.6.0 and fixes persist api introduced in v3.6.3.

    What's Changed

    • fix(types): fix core types to better handle middleware types by @dai-shi in https://github.com/pmndrs/zustand/pull/641
    • feat(middleware): add onFinishHydration to persist api by @AnatoleLucet in https://github.com/pmndrs/zustand/pull/646

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.4...v3.6.5

    Source code(tar.gz)
    Source code(zip)
  • v3.6.4(Nov 3, 2021)

    This improves devtools middleware and typing of other middlewares. Please feel free to update and report any issues.

    What's Changed

    • feat(middleware): devtools to patch api.setState with namedSet and fix middleware types by @dai-shi in https://github.com/pmndrs/zustand/pull/634

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.3...v3.6.4

    Source code(tar.gz)
    Source code(zip)
  • v3.6.3(Nov 2, 2021)

    The new persist middleware exposes persist api in store. This is thanks to the new customizable store api types introduced in v3.6.

    What's Changed

    • fix(core): useDebugValue in useStore by @dai-shi in https://github.com/pmndrs/zustand/pull/622
    • feat(middleware): add persist api by @AnatoleLucet in https://github.com/pmndrs/zustand/pull/624
    • refactor(types): prefer type alias by @dai-shi in https://github.com/pmndrs/zustand/pull/625

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.2...v3.6.3

    Source code(tar.gz)
    Source code(zip)
  • v3.6.2(Oct 30, 2021)

    v3.6.0 introduced middleware types trying to infer store types as much as possible. However, it doesn't work well for several cases, and users need to type manually which was actually hard. In this version, middleware types are simplified and let users to explicitly type when needed more easily. Many examples are in tests/middlewareTypes.test.tsx. If you find issues or need some more typing examples, please report them.

    What's Changed

    • fix(middleware): simplify middleware types and allow explicit typing by @dai-shi in https://github.com/pmndrs/zustand/pull/617

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.1...v3.6.2

    Source code(tar.gz)
    Source code(zip)
  • v3.6.1(Oct 26, 2021)

    Summary

    This fixes some type issues introduced in v3.6.0. devtools is improved to accept updating state from DevTools Ext.

    What's Changed

    • fix(context): custom store type for createContext by @dai-shi in https://github.com/pmndrs/zustand/pull/606
    • feat(middleware): devtools dispatch support by @Aslemammad in https://github.com/pmndrs/zustand/pull/608
    • fix(middleware): types and devtools by @dai-shi in https://github.com/pmndrs/zustand/pull/613

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.6.0...v3.6.1

    Source code(tar.gz)
    Source code(zip)
  • v3.6.0(Oct 21, 2021)

    Summary

    This version mainly comes with type improvement for middleware. It's tricky implementation-wise. Please report issues and let's look for solutions or workarounds. It has renamed and deprecated types: UseStore ๐Ÿ‘‰ UseBoundStore A new subscribeWithSelector middleware is added, deprecating the equivalent feature in core.

    Migrating to subscribeWithSelector middleware

    Previously, you could do this:

    const useStore = create(...)
    useStore.subscribe(callback, selector, equalityFn)
    

    which is deprecated and replaced with:

    const useStore = create(subscribeWithSelector(...))
    useStore.subscribe(selector, callback, { equalityFn }) // selector is not optional
    

    What's Changed

    • feat(types): better middleware support by @dai-shi in https://github.com/pmndrs/zustand/pull/601
    • fix(types): Rename from UseStore to UseBoundStore by @dai-shi in https://github.com/pmndrs/zustand/pull/595
    • feat(middleware): subscribeWithSelector middleware by @dai-shi in https://github.com/pmndrs/zustand/pull/603

    New Contributors

    • @benj-dobs made their first contribution in https://github.com/pmndrs/zustand/pull/602

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.5.14...v3.6.0

    Source code(tar.gz)
    Source code(zip)
  • v3.5.14(Oct 19, 2021)

    Summary

    Fixed a regression in devtools that was introduced in v3.5.11.

    What's Changed

    • fix(middleware): export PersistOptions type definitions by @abraaoz in https://github.com/pmndrs/zustand/pull/588
    • fix(middleware): jump state support in devtools by @Aslemammad in https://github.com/pmndrs/zustand/pull/590

    New Contributors

    • @abraaoz made their first contribution in https://github.com/pmndrs/zustand/pull/588

    Full Changelog: https://github.com/pmndrs/zustand/compare/v3.5.13...v3.5.14

    Source code(tar.gz)
    Source code(zip)
  • v3.5.13(Oct 7, 2021)

    The persist middleware has a new option partialize which works for nested properties, deprecating blacklist and whitelist options.

    • #463 feat(persist): add partialize option
    Source code(tar.gz)
    Source code(zip)
  • v3.5.12(Oct 1, 2021)

    v3.5.11 accidentally requires newer node.js versions. v3.5.12 fixes it by reverting exports format.

    • #578 fix(package): avoid subpath pattern in exports
    Source code(tar.gz)
    Source code(zip)
  • v3.5.11(Sep 28, 2021)

    โš ๏ธ Minimum Node.js requirements (for server-side usage like Next.js): v14.13.0, v12.20.0

    This improved devtools middleware. There can still be room for improvement. Free free to open issues and feature requests, and possibly contribute to them.

    • #560 Fix: remove useless internal info in devtools
    • #558 chore(build): simplify exports and support nested subpath
    Source code(tar.gz)
    Source code(zip)
Owner
Poimandres
Open source developer collective
Poimandres
๐Ÿ High performance subscription-based form state management for React

You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of React Final Form.

Final Form 7.2k Jan 7, 2023
A state management library for React, heavily inspired by vuex

Vuex - But for React! โš› If you know vuex, you know it's as close as we get to a perfect state management library. What if we could do this in the reac

Dana Janoskova 103 Sep 8, 2022
Twitter-Clone-Nextjs - Twitter Clone Built With React JS, Next JS, Recoil for State Management and Firebase as Backend

Twitter Clone This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn de

Basudev 0 Feb 7, 2022
Create a performant distributed context state by synergyzing atomar context pieces and composing reusable state logic.

Synergies Create a performant distributed context state by synergyzing atomar context pieces and composing reusable state logic. synergies is a tiny (

Lukas Bach 8 Nov 8, 2022
๐Ÿ”ฎ tiny robust state management

?? snapstate tiny robust state management ?? npm install @chasemoskal/snapstate ??๏ธ watch for changes to properties ??๏ธ track only the properties you

Chase Moskal 5 Dec 23, 2022
A tiny package for JavaScript Web App's state management based on RxJS & Immer

A tiny package for JavaScript Web App's state management based on RxJS & Immer

Xiao Junjiang 12 Oct 19, 2022
Tiny and powerful state management library.

BitAboutState Tiny and powerful React state management library. 100% Idiomatic React. Install npm install --save @bit-about/state Features 100% Idioma

null 53 Nov 5, 2022
Learning how to use redux - a state management library

Redux Learning how to use redux - a state management library What is Redux? Redux is a state management library for JS apps. It centralizes applicatio

Melvin Ng 3 Jul 18, 2022
A Higher Order Component using react-redux to keep form state in a Redux store

redux-form You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of Redux

Redux Form 12.6k Jan 3, 2023
experimental project for babel-plugin-mutable-react-state

Goalist Mutable React Example This example is an attempt to work with babel-plugin-mutable-react-state on a simpler project to see how complicated wou

Reaper 1 Jun 7, 2022
Whoosh - minimalistic React state manager

Whoosh - minimalistic React state manager Whoosh is a React state manager which entire API consists of exactly one function - createShared(). TL;DR ve

Alexander Blk 9 Nov 7, 2022
React Native's Global Alert Component that can be fully customized and without the need of a state.

?? React Native Easy Alert React Native Easy Alert Component. Watch on youtube Easy Alert example app. React Native's Global Alert Component that can

null 9 Feb 21, 2022
Small (0.5 Kb) react hook for getting media breakpoints state info in runtime

tiny-use-media Small (0.5 Kb) react hook for getting media breakpoints state info in runtime Usage npm i tiny-use-media --save Adn in your react code

Valeriy Komlev 51 Dec 13, 2022
Edvora App is a web application based on an external API, showing data about different types of products and the user can filter these data by choosing a specific state, city or product name. Build with React.js

Edvora App is a web application based on an external API, showing data about different types of products and the user can filter these data by choosing a specific state, city or product name. Build with React.js

Kyrillos Hany 5 Mar 11, 2022
React Query wrapper for NextAuth.js session management

NextAuth.js React-Query Client @next-auth/react-query React Query wrapper for NextAuth.js session management. Overview This is an alternative client f

NextAuth.js 124 Dec 16, 2022
Real state property listing app using next.js , chakra.ui, SCSS

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

null 1 Dec 19, 2021
This hook allows you to isolate and manage the state within the component, reducing rendering operations and keeping the source code concise.

React Hook Component State This hook allows you to isolate and manage the state within the component, reducing rendering operations and keeping the so

Yongwoo Jung 2 May 15, 2022
๐Ÿ–ฑor โŒจ๏ธ? ๐Ÿคทโ€โ™€๏ธ, but hopefully use-hover-state works on the "user intent" not the "device"

useHoverState() The one aware of keyboard navigation as well ?? npm i use-hover-state A React hook for tracking user interaction with the DOM elements

Marina 10 Aug 11, 2022
a babel plugin that can transform generator function to state machine, which is a ported version of typescript generator transform

Babel Plugin Lite Regenerator intro This babel plugin is a ported version of TypeScript generator transform. It can transform async and generator func

Shi Meng 6 Jul 8, 2022