The simple but very powerful and incredibly fast state management for React that is based on hooks

Last update: Aug 8, 2022

Hookstate

The simple but very powerful and incredibly fast state management for React that is based on hooks.


Why?Docs / SamplesDemo applicationPluginsRelease notes

Preface

Hookstate is a modern alternative to Redux, Mobx, Formik without boilerplate. It is simple to learn but very flexible to use. It has got impressive performance and predictable behavior.

Any questions? Just ask by raising a github ticket.

Why Hookstate

hookstate.js.org

Migrating to version 3

hookstate.js.org/docs/migrating-to-v3

Documentation / Code samples

hookstate.js.org/docs/getting-started

Demo application

hookstate.js.org/demo-todolist

Development tools

hookstate.js.org/docs/devtools

Plugins / Extensions

hookstate.js.org/docs/extensions-overview

API reference

hookstate.js.org/docs/typedoc-hookstate-core

GitHub

https://github.com/avkonst/hookstate
Comments
  • 1. Add next js demo. Was: Warning when using Hookstate with Next.JS

    Hello,

    I am receiving a warning when I use Hookstate with NextJS.

    Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.

    I am not able to find any instruction on how to use Hookstate with Next.

    Any help is greatly appreciated.

    Reviewed by ermaliii at 2021-09-06 11:53
  • 2. Question: Example Application

    Any applications in the wild currently using this that you're aware of? The library seems really interesting and all the demo snippets are fantastic, but coming from a redux background I'm trying to wrap my head around how it'd be implemented in a real-world application. Specifically in terms of architecture and recommended design patterns.

    Reviewed by eddielee394 at 2019-11-06 01:50
  • 3. Add StateLink.merge from Mutate plugin (WAS: Using Mutate for stateRef)

    createStateLink({a: 1}).with(Mutate) does not work, throws an error Is it supposed to work like this ? Also, I see in the Mutate example: Mutate(state) But in validation example I see Validation(state) but also .with(Validation)

    I would like to do it once with(mutate) and use Mutate functions everywhere

    useStateLink(FieldStore).with(Mutate) doesn't work as well

    Reviewed by lishine at 2019-11-27 11:14
  • 4. Question: Subscribing to nested changes at a parent level

    Hi avkonst,

    Amazing library you've built here. It looks exactly like the type of thing I was imagining. I'm going through evaluating libraries to try to get to a less hacky way of implementing state.

    I had a question on a specific use case that's not obvious to me if hookstate would handle well (or could have a plugin written to handle).

    I have a large recursive nested structure, basically a workflow of questions and answers which lead to more questions then more answers and so on. I've built a hacked-together solution with regular react components (well, preact), where the top-level component has the entire tree as a state variable, passing down sections of the tree to its children, and then each nested component has an oninput that mutates its section of the tree directly and then calls forceUpdate(). This works because the tree of Components mirror the tree of the state, so forceUpdate() correctly cascades for the corresponding subtree. I'm sure many would cry at this implementation, but it works well enough.

    In hookstate, it looks like nested combined with the usage of scoped states would work well enough as a replacement here. The subtree would get passed in to each component, and it would be able to set on the scoped state oninput, which should then update the state and trigger a render.

    Then, I support undo/redo functionality, by changing the top-level state tree into a proxy, so when anything is set or delete, I store a snapshot of the whole tree, and then undo/redo buttons just setState the whole tree with the snapshot, so everything renders as normal.

    This is then where I'm not sure how I would implement this snapshot/apply functionality in hookstate. I think what I would want is some way to know at the top-level (or maybe even any nested level) that there is a change down the line, so that I can know to store a snapshot. There is a Touched plugin demo that shows the parent knows when it was touched, but do those just store a one-time flag for the first change? Or is there some way to subscribe to any changes? This also makes me think about things like time travel, though I think maybe your library specifically chose to eschew this functionality.

    Maybe I'm thinking about this the wrong way, and it would just be most straightforward to add a transform for saveSnapshot and have the Component oninput function just call that after state set.

    Any thoughts/advice?

    Reviewed by jmchuster at 2020-04-05 09:39
  • 5. Support setting/getting undefined paths

    Use Case:

    There is a form object (say, DTO for REST or GraphQL parameter), that has nested optional arguments:

    interface Argument {
      root: string;
      nested?: {child: string}
    }
    

    Currently, in order for hook state to support writing to nested objects which do not exist yet, you have to put empty objects in the state:

    const state = useState({root: 'foobar', nested: {} as any});
    

    If you do not insert an empty object, code like this will break:

    
    const scoped = useState(state);
    
    // nested = undefined error
    scoped.nested.child.set('wee');
    

    Currently my project has these empty objects defined everywhere and this is something that can easily bite you at runtime depending on how things are setup.

    Is it feasible for the library to support constructing missing object paths?

    Reviewed by parisholley at 2021-09-06 21:26
  • 6. Allow State to be used in dependency lists for React.useEffect, React.useMemo, etc. and as prop for React.memo

    First of all, thank you for this awesome lib!

    I found myself having difficulties trying to find the right way to implement some state updates efficiently, and the following reflexion arose:

    What about using Immer? Thanks to its support for patches, would allow this lib to support a wider range of operations, on all sort of data types. set and merge methods could be replaced by produce, and plugins could leverage patches (which would be useful for my plugin).

    I really like the whole intelligent proxy system that is currently in place, and I honestly think that putting Immer in there would make the whole lib even better!

    I wonder if this is something possible? Or is there some limitations or willingness to keep everything inside hookstate itself?

    Reviewed by magne4000 at 2021-02-23 11:51
  • 7. Documentation for Devtools for Hookstate (released: @hookstate/devtools)

    Here is the prototype of devtools. It injects to Hookstate as a standard plugin, which submits state changes to Redux DevTools. Should I finalise it? Please comment / react to express your interest.

    Here is the screenshot: image

    Reviewed by avkonst at 2020-02-10 06:06
  • 8. Unintentional Synching of Parent and Child Components States

    I'm sending an object state as a prop down to the child to be set as an initial value of the child state. Now I'm using the recommended way to do this as highlighted in 102 exception.

    Then I simply mutates the child state but find "initial value" prop getting updated too. This is undesirable and I can't seem to understand the reason for this behavior.

    I'm using v3.0.13

    Here's the code snippet:

    const ParentComponent = () => {
       const parentState = useState({ a: [1, 2], b: [2, 3], c: [4, 5] });
      
      return (
         <ChildComponent  
               initalVal={JSON.parse(JSON.stringify(parentState.get()))}
          />
      );
    };
    
    const ChildComponent = ({ intialVal }) => {
       const childState = useState(initialVal);
    
       const updateChildState = () => {
             childState.a.set(p => {
                    p.splice(1, 1);
                    return p;
             });
       }; 
    
      return (
           <Text>Initial A : {JSON.stringify(initalVal.a)}</Text>
           <Text>Updated Child State A: {JSON.stiringify(childState.a.get())}</Text>
           <Button
                ...
                onPress={updateChildState}
           />
      );
    };
    

    Expecting: Initial A: [1, 2]

    Actually getting: Initial A: [1]

    Reviewed by waleedshkt at 2022-07-20 00:44
  • 9. Simpler and more intuitive way to do attach(Downgrade)

    We tried to implement hookstate into our serverless app and we needed to send objects from the state to the firebase database. However, in order to do so, we needed to do the following:

    const data = myState.attach(Downgraded).get()
    

    This has one main issue, which is the reason we scrapped hookstate in favor of something else. It's not intuitive, a person who hasn't read the docs a couple of times won't know what is going on. It's also really counter intuitive how .get() returns you a proxy, which can't be used directly in JSON API request. I get that there has to be a reason to force everything to need Downgraded attached to get the pure value, but the way it has to be done is ugly. I suggest creating a function toObject() which can attach Downgraded internally, but it just has better code flow. The example from above would become the following:

    const data = myState.toObject().get()
    

    or

    const data = myState.get().toObject()
    
    Reviewed by bmutafov at 2021-10-01 19:17
  • 10. Proposal to improve Validation plugin

    I was initially stuck because I wanted my navigation to show badges when "tabs" had validation issues, but didn't want to re-render all the tabs on change. Initially I was doing

    state.array.forEach(a => {
      Validation(a.name).validate(a => a.length > 0, 'Name required');
    });
    

    The problem with the above though is it will now subscribe my tab/navigation to any validation failures and cause a full re-render of all children.

    Once I dug into the code I realized I could write it like this:

    Validation(a.array[0].name).validate(a => a.length > 0, 'Name required');
    

    Which actually ends up wildcarding behind the scenes, but not clear from the syntax. At the very least would be helpful to document this current behavior, but I think a more idiomatic syntax would be:

    Validation(a.array).forEach(a => {
    a.name.validate(a => a.length > 0, 'Name required');
    });
    
    Reviewed by parisholley at 2020-08-13 13:04
  • 11. Nesting stores example

    Is there an example to nest stores? For example, if I need all stores to be nested under one store. Or when I attach a store dynamically. It could be needed for SSR or for persistance. With Next.js, this was the reason why I used react-easy-peasy - one global store.

    Reviewed by lishine at 2019-11-30 09:26
  • 12. add into() method to state

    let a: State<{ a: number, b: string }> & { downcast<S extends Partial<{ a: number, b: string }>>(): State<S>; };
    let b: State<{ a: number }> = a!.downcast();
    let c: State<{ a: number }> = (a!);
    
    function downcast<S1, S2 extends S1, E>(a: State<S2, E>): State<S1, E> {
        return {} as State<S1, E>
    }
    
    Reviewed by avkonst at 2022-08-04 11:32
  • 13. localstored from @hookstate/localstored for React Native

    i want to create global state with persist (@hookstate/localstored) in React Native could someone give me reference??

    i just create global state for authentication flow, but everytime I close and open the page, it return to initialState. i think it should be store at persist or local storage in React Native.

    Reviewed by twinedo at 2022-07-31 08:23
  • 14. Document how to combine extensions to create a new extension

    // TODO document this sample // // creating reusable combo // let e = () => extend( // clonable(v => v), // clonable(v => v), // // clonable(v => v), // // clonable(v => v), // initializable(s => { // return '' // }) // )(); // // double initialize // let a = createHookstate([1], extend(e, initializable(s => { // s.initialized // return '' // }))) // a.initialized

    // let b = createHookstate([1], initializable(s => { // return s.get() // }))

    Reviewed by avkonst at 2022-07-30 00:24
  • 15. use serializable and identifiable extensions in broadcasted and devtools extensions

    Broadcasted/Devtools can broadcast only certain types. If serializable extension is added to a state, the broadcased/devtools extension could use this (like localstored extension) to pack/unpack broadcasted data. This would allow to support advanced custom user's types in a state with the broadcasted/devtools plugin.

    Reviewed by avkonst at 2022-07-25 08:57
  • 16. Document how to add extension method setWithContext (WAS: Feature request: Allow me to pass meta data to plugins.)

    Hi, have been using hookstate for a while now and it seems pretty cool. We are running into a problem which I think could most easily be solved by allowing us to pass some meta data to plugins. I'll try to explain what we are doing and I'd like to hear your thoughts.

    We would like to be able to update the store without updating everything to the server. The easiest way (I think) would be with meta data so we could set something like: skip_backend_save: true. That way we could have a grip on when updating to the server and when not.

    What are you doing?!:

    We are currently working on pushing our changes to other users on a page. The setup we choose is in short this:

    1. User answers a question
    2. Plugin detects answer and pushes to server
    3. Server saved and broadcasts to other users via websockets (Rails actioncable)
    4. Other users receive new data, we update store.
    5. Store detects changes, back to 2.

    5 is where things go south for us and where some meta data would really help us out. Then we could just update the stores with a 'skip_backend_save' flag. Something like this: answer.set(data, meta) would be enough.

    We have found a 'kinda hacky' way around it for now. But we would like to know how you feel about this idea.

    Reviewed by doncuomo at 2022-07-14 08:13
A hooks-based lightweight React library for state management

React async states A naive lightweight React library for managing state. What is this ? This is a library for decentralized state management in React.

Jul 16, 2022
Recoil provides a fast and flexible way to share state across components with React Hooks Api.

umi-plugin-recoil A plugin for [email protected] to help you set RecoilRoot. What is Recoil? Recoil provides a fast and flexible way to share state across com

Jul 19, 2022
A simple yet powerful finite state machine React hook.

@rkrupinski/use-state-machine A simple yet powerful finite state machine React hook. const [state, send] = useStateMachine({ initial: "enabled", s

Jun 12, 2022
Simple and powerful API client for react. Use hooks to fetch data in easy way.

Simple and powerful API client for react. Use hooks to fetch data in easy way.

Apr 2, 2022
tiny state management for react with hooks

a simple state management for react using hooks purpose In some simple project, there are some state management requirement, but redux is too heavy to

Feb 28, 2022
State management that tailored for react, it is simple, predictable, progressive and efficient.
State management that tailored for react, it is simple, predictable, progressive and efficient.

English | 简体中文 ⚡️ State management that tailored for react, it is simple, predictable, progressive and efficient. ?? Introduction Concent is an amazin

Aug 3, 2022
💫 Tiny and powerful hook-based event system for React

BitAboutEvent ?? Tiny and powerful hook-based event system for React. 100% Idiomatic React.

May 12, 2022
React debounce hooks based on state changed.

Debounce Hooks React debounce hooks based on state changed. Live Preview / Demo In Here Installation npm i @bakunya/debounce-hooks Basic Usage Note d

Apr 29, 2022
A hook that will save you from endless scrolling problems! Infinite scrolling that really works and is very easy to integrate

A hook that will save you from endless scrolling problems! Infinite scrolling that really works and is very easy to integrate! This hook allows you to create simple, lightweight components with infinite scrolling in all directions, supporting both windowed and scrollable elements.

Aug 3, 2022
Simple global state for React with Hooks, which just depends on React's useEffect and useState.

react-hooks-simple-global-state Simple global state for React with Hooks, which just depends on React's useEffect and useState. The idea here is simpl

Aug 5, 2022
A state management library for React, Vue.js, Angular and vanilla javascript

Diffx Introduction Diffx is a state management library that focuses on being easy to learn and use, and to offer a great development experience at any

May 14, 2022
A state management library for React with built-in undo, redo, and persistence.
A state management library for React with built-in undo, redo, and persistence.

Out of nowhere! A state management library for React with built-in undo, redo, and persistence. Built on Zustand.

Jul 25, 2022
Dead simple yet powerful countdown hook for React.
Dead simple yet powerful countdown hook for React.

Dead simple yet powerful countdown hook for React. Powered by requestAnimationFrame. Installation Using npm: $ npm install --save react-countdown-hook

Aug 1, 2022
A simple yet powerful library for managing global states with react

react-global-state This package consists of simple global states made possible by observing browser events. It works well when you need to use global

Jul 27, 2022
Simple global state for React with Hooks API without Context API

react-hooks-global-state Simple global state for React with Hooks API without Context API Introduction This is a library to provide a global state wit

Aug 9, 2022
React Hook for state management with profunctor lenses

Profunctor State Hook React Hook for state management with Profunctor Optics A simple and small (2KB!) approach to state management in React using fun

Mar 23, 2022
A new react state management framework
A new react state management framework

A new react state management framework System functions 1. Simple State A simple state management tool that looks similar to recoil, used to manage sc

Jun 29, 2022
A state management library that follows the React component model

?? klyva Scalable state management for React. Minimal API, with reactive, composable and decomposable state! ?? 10 minute tutorial How to Create an at

Jul 9, 2022
📠 React custom hook for persist state management
📠 React custom hook for persist state management

Little State Machine State management made super simple ✨ Features Tiny with 0 dependency and simple (715B gzip) Persist state by default (sessionStor

Aug 2, 2022