dai-shi / react-hooks-global-state

[NOT MAINTAINED] Simple global state for React with Hooks API without Context API

Home Page:https://www.npmjs.com/package/react-hooks-global-state

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

getState for non-redux version

vans163 opened this issue · comments

There is no getState for createGlobalState (the one you use without redux).

So its not possible to get the state inside a non-react functional component without write this hack.

    var state;
    setGlobalState('login', v => {
      state = v;
      return v;
    });

Hm, but why do you want a copy of global state?

This library by design doesn't expose entire global state.
The apis are only allowed to access a part of global state by a property name.
getState by createGlobalStore is just an exception to mimic Redux.

Oh, I may misunderstood. You want to read state outside react like getGlobalState('login').
It sounds like you want something like Redux middleware, which is not currently possible with createGlobalState. Hmmm.

How would you handle a function like:

function apiCall() {
    var i_want_state;
    var do_stuff_with_state = i_want_state.key;
}

useGlobalState does not work here, as this is not a react component. I simply exported getState + write a getState/1, and it works great for me. So I can do now..

var full_state = getState();
var keyed_state = getState("navbar");

Maybe this should be added?

function apiCall() {

How would you call this? If this were called from useEffect, you could pass a state as a argument.

I really hesitate exporting getState which is likely to be misused, but at the same time I do understand without it, we are not providing the same-level api as createStore can do with middleware.

I would like to understand your use case: apiCall not triggered by useEffect but needs to read state?

Hm, interesting:

https://twitter.com/dai_shi/status/1132427865654349825

This library keeps global state outside of React. (which BTW is not a good design, hm I might be able to fix it.)

The moment after I start thinking about the design again, it seems to me that one of the values of this library is actually "keeping a copy of global state" outside of React. That would only allow us to use Redux-like middleware. And it would rather make sense to provide the same API for createGlobalState.

which is likely to be misused

Let me try limiting getState can only be called outside of React.

"How would you call this? If this were called from useEffect, you could pass a state as a argument."

Calling it from ANYWHERE is broken (even inside a component). It does not work. Here is another example:

function apiQueryDatabase() {
    if (now() - CANT_GET_STATE.last_query >= 5000) {
        updateGlobalState(.., loading: true)
        await query();
        updateGlobalState(.., loading: false, last_query: now())
    }
}

Notice CANT_GET_STATE, basically we have no way to reference the state here, and MUST use redux. Why cannot do this without redux?

I was thinking about re-designing to be more hook-friendly, but gave up for now.

For now, the best is to add getGlobalState. Two things to note.

  • needs to pass name.
  • can't use inside render.

Please try #18 and let me know how it works or not.

Why cannot do this without redux?

To be clear, my recommendation of this library is createGlobalState, and createStore is only an option for people who would really want it. So, your feedback is valuable for me.

CANT_GET_STATE.last_query

I'm curious, in this example, do you have a component render with last_query? Otherwise, I wouldn't put in the globalState, but just keep in a variable.

I'm curious, in this example, do you have a component render with last_query? Otherwise, I wouldn't put in the globalState, but just keep in a variable.

I use a differential state system. The backend always sends the frontend the updated state via WebSockets. So state does not soley start/end at the frontend for me, I have responsive realtime state between multiple sessions (if same user) across different computers, as soon as 1 user updates something, all users must get the update immediately.

The simplest way to achieve this for me and to prevent tons of extra network traffic, was to use evented streaming state differentials.

Hence why I often need to getState, simply to check what the state differential spit out. Using local state could work, but often I found that it was always missing something, like I would need to xref something in globalState regardless, then I would have to start caching a bunch of stuff locally and passing a buncha args, very quickly the code becomes a mess and we regress to react+classes.

@vans163 Haven't had a chance to try #18? Just pinging you to see if you are still interested in it. No rushing.

Ah let me try it. So getWholeGlobalState() to get all state, and getState(key) for keyed?

Actually not. Only exported for createGlobalState is getGlobalState(key).

Is it possible to export both? Just for utility? Give a person a swiss army knife, not a fork, a knife, and scissors as 3 separate objects.

Is it possible to merge this into master?

In short, I would only export keyed API.
If someone really need a whole object, one can do the following:

const getWholeGlobalState = () => {
  const obj = {};
  Object.keys(initialState).forEach((key) => {
    obj[key] = getGlobalState(key);
  });
  return obj;
};

This is a bit of extra work, and one should use getGlobalState(key) whenever possible.


What's important here is that the fact that this library uses observedBits is an implementation detail,
and React may drop this API at any time. If it's simply dropped, I would change the implementation to use multiple contexts and the getWholeGlobalState might be implemented just like the above. I believe that exporting getWholeGlobalState encourages the misuse of it.

The problem with useGlobalState again is, it only works inside react components. Maybe I am missing the correct way to create a root level store like redux does, due to my lack of react skills.

@vans163 Oops, sorry. I meant getGlobalState(key).

Anyway, let's merge #18.