-
-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comparison with related projects #1
Comments
Hm, I think context value in constate and unstated-next is state-based object as well. More precisely, output of useValue hook. Updated. |
Benchmark results for react-tracked, reactive-react-redux and react-redux. |
Could you please add https://github.com/atlassian/react-sweet-state to the comparison |
Added in the table. (Do you also mean to the benchmark? |
To be honest I am more concerned about API and edge cases, as long as the majority of the work I am doing is faaaaaaaaar from real time. |
I wonder how you would evaluate edge cases... |
All alternate state managers were created to solve some edge cases. You may try to figure out that problem (and in which way) some library was intended to solve, and try to apply the same case to another library)
|
There was a misunderstanding of mine about react-sweet-state. It uses readContext. Modified. Yeah, zustand by @drcmda is only a popular library with non-context solution. I've seen small/experimental libraries without context though. |
I made a minimal example to compare actual bundle size with some libraries. Build JS sizes$ cd examples/counter-react-tracked
$ wc build/static/js/*.js
1 2263 123254 build/static/js/2.0c3afdb5.chunk.js
1 16 1066 build/static/js/main.088f65ad.chunk.js
1 37 1502 build/static/js/runtime~main.a8a9905a.js
3 2316 125822 total
$ cd examples/counter-constate
$ wc build/static/js/*.js
1 2190 120150 build/static/js/2.f7ca4f1e.chunk.js
1 16 1109 build/static/js/main.e21dfac9.chunk.js
1 37 1502 build/static/js/runtime~main.a8a9905a.js
3 2243 122761 total
$ cd examples/counter-zustand
$ wc build/static/js/*.js
1 2222 121214 build/static/js/2.20ef84af.chunk.js
1 18 1079 build/static/js/main.44ecf751.chunk.js
1 37 1502 build/static/js/runtime~main.a8a9905a.js
3 2277 123795 total
$ cd examples/counter-reactive-react-redux
$ wc build/static/js/*.js
1 2976 148172 build/static/js/2.40846575.chunk.js
1 18 1117 build/static/js/main.e8a6d259.chunk.js
1 37 1502 build/static/js/runtime~main.a8a9905a.js
3 3031 150791 total
|
https://github.com/reusablejs/reusable by @adamkleingit and @morsdyce |
You may want to include https://github.com/avkonst/react-use-state-x to your research too. It is tiny, type-safe, feature-rich useState-like React hook to manage complex state (objects, arrays, nested data, forms) and global stores (alternative to Redux/Mobx). It's size is reported here: https://bundlephobia.com/[email protected] but it includes Typescript headers too. |
It would be interesting to see it's performance, but I have not done much about optimising the linear performance. I was more focused on reducing number and "size' of renders on state changes. |
react-powerplug in hooks form 👍 |
@avkonst If I understand your implementation correctly, Observer triggers re-render for any state change. That’s just like the normal context. So, I might be misunderstanding something. It would be nice if there were a minimal example in codesandbox for global state. |
Where can I find react-powerplug hooks form? |
Yes, you are right. Observer is essentially a context provider. React knows
nested components dependent on the context. The ones which call
useStateLink in our case.
You can use the same observer multiple times, in the deeply nested
hierarchy of Dom tree. Change in the global state will trigger context
change for all the observers of the linked / related store.
You can also have multiple global stores. For example one about user state,
another about apps settings,etc. In this case observers of the affected by
a change store will trigger rerender, but not the other.
…On Thu, 11 Jul 2019, 21:24 Daishi Kato, ***@***.***> wrote:
@avkonst <https://github.com/avkonst> If I understand your implementation
correctly, Observer triggers re-render for any state change. That’s just
like the normal context. So, I might be misunderstanding something. It
would be nice if there were a minimal example in codesandbox for global
state.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1?email_source=notifications&email_token=AA6JSVJUDXN23CYELBX4YXTP6333DA5CNFSM4HZBGGMKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZWDCBQ#issuecomment-510406918>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA6JSVKHZ2YTULALRANFMHLP6333DANCNFSM4HZBGGMA>
.
|
So not quite “tracked” ;) |
For your table for react-use-state-x. |
The change to the value in the store is done via ValueLink set API, it is not js proxy and has got other functions, eg validate state according to user's validators. |
So, If I were to add an item:
Don't worry too much about the bundle size. Mine also includes unused functions. If you are interested, create a simple counter example and compare. As far as I understand, your library focuses on mutating state in a good way. That said, I'm getting to understand your lib. |
The table addition looks good. You may expand optimisations column like
'multiple stores, multiple deeper placed observers/contexts, derived per
component local state cache'
useStateLink link is effectively useState which returns a ValueLink with
value and set properties instead of an array of value and set function. If
useStateLink is called to bind with global store, it returns ValueLink to
mutate the global store. Observer is not influencing the design of the
ValueLink, it is built on top of it. Main complexity of the ValueLink is
due to strict typesafety for value access and mutation ops. I guess it
could be implemented using proxy, but it would be a problem to support
validation features this way. Also I like the idea of separate explicit
'set' action, which I know should be called in reactions but not during
render. Hope it helps.
…On Thu, 11 Jul 2019, 23:19 Daishi Kato, ***@***.***> wrote:
So, If I were to add an item:
Context value Using subscriptions Optimization for big state object
Dependencies Pakage size
react-use-state-x <https://github.com/avkonst/react-use-state-x> mutable
reference to state object (which is basically equivalent to store) Yes
(observer pattern?) Multiple stores No 2.9kB
***@***.***>
Don't worry too much about the bundle size. Mine also includes unused
functions. If you are interested, create a simple counter example and
compare
<#1 (comment)>
.
As far as I understand, your library focuses on mutating state in a good
way.
My comparison table is about re-renders for state updates. (no mutation in
mind)
------------------------------
That said, I'm getting to understand your lib. useStateObject and
useStateArray are easier to get.
Whereas useStateLink looks a bit complex to me, maybe because I'm not
very used to observer.
BTW, if you are OK with using Proxy, link.value can do the same job of
link.nested, something like immer but different. (Ah, is it like MobX?)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1?email_source=notifications&email_token=AA6JSVO5UA5ZOYDPD4LUNBTP64JM5A5CNFSM4HZBGGMKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZWMJRQ#issuecomment-510444742>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA6JSVJVCCLYVNVCRQLBOCDP64JM5ANCNFSM4HZBGGMA>
.
|
In relation to your question about nested. It is not like mobx. Mobx
required required a lot more boilerplate.
Nested and inferred functions of ValueLink are described in the
documentation. If it was not needed to develop strongly typesafe API, the
ValueLink could combine all properties from nested and inferred, but I see
it is a disadvantage to blur the type of the value and mutation ops allowed
over this value.
…On Thu, 11 Jul 2019, 23:53 Andrey Konstantinov, ***@***.***> wrote:
The table addition looks good. You may expand optimisations column like
'multiple stores, multiple deeper placed observers/contexts, derived per
component local state cache'
useStateLink link is effectively useState which returns a ValueLink with
value and set properties instead of an array of value and set function. If
useStateLink is called to bind with global store, it returns ValueLink to
mutate the global store. Observer is not influencing the design of the
ValueLink, it is built on top of it. Main complexity of the ValueLink is
due to strict typesafety for value access and mutation ops. I guess it
could be implemented using proxy, but it would be a problem to support
validation features this way. Also I like the idea of separate explicit
'set' action, which I know should be called in reactions but not during
render. Hope it helps.
On Thu, 11 Jul 2019, 23:19 Daishi Kato, ***@***.***> wrote:
> So, If I were to add an item:
> Context value Using subscriptions Optimization for big state object
> Dependencies Pakage size
> react-use-state-x <https://github.com/avkonst/react-use-state-x> mutable
> reference to state object (which is basically equivalent to store) Yes
> (observer pattern?) Multiple stores No 2.9kB
> ***@***.***>
>
> Don't worry too much about the bundle size. Mine also includes unused
> functions. If you are interested, create a simple counter example and
> compare
> <#1 (comment)>
> .
>
> As far as I understand, your library focuses on mutating state in a good
> way.
> My comparison table is about re-renders for state updates. (no mutation
> in mind)
> ------------------------------
>
> That said, I'm getting to understand your lib. useStateObject and
> useStateArray are easier to get.
> Whereas useStateLink looks a bit complex to me, maybe because I'm not
> very used to observer.
> BTW, if you are OK with using Proxy, link.value can do the same job of
> link.nested, something like immer but different. (Ah, is it like MobX?)
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <#1?email_source=notifications&email_token=AA6JSVO5UA5ZOYDPD4LUNBTP64JM5A5CNFSM4HZBGGMKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZWMJRQ#issuecomment-510444742>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AA6JSVJVCCLYVNVCRQLBOCDP64JM5ANCNFSM4HZBGGMA>
> .
>
|
Will add it to the comparison table. I think I understand your point. As you may know my another library react-hooks-global-state has type-safe mutation but just for a (shallow) object, so it's like your Speaking of types, I found typing in immer works well. I didn't realize Proxy helps typing mutation operations. I have an interesting idea, If you expose a custom hook for local state, it can work with react-tracked nicely. Wait a minute, you already have one |
https://codesandbox.io/s/react-tracked-example-trb02 If you understand what's going on, here's my suggestion: if you focus on creating a custom hook for local state that has handy setter (with typing), you can turn into global state with react-tracked, constate or anything you like. As I guess typed setters are the strength of your library, let the job for global state out. |
Thanks. I will have a look. I do not understand now how usetracked hooks into ValueLink :) |
I understand your lib uses undocumented internal API. I am a bit concerned that it maybe gone in the future... What do you think? |
I'd expect when they obsolete the unstable API, a new proper API will be provided.
If I understand correctly, if one uses multiple stores, they will use context provider for each store (in this case a You could put multiple stores in a context (see reusable), but it doesn't seem to be so in your lib. |
OK. I see what you are doing in your library. Tracking of used within a component props matched with detected changes to force update for the affected subscribers. I think tracking has got the potential. I have tried the approach with subscribers in the past (just subscribers, not the tracking) and got performance issues on the use case like this (it is artificial to demonstrate what happens when nested components rerender too):
I found that plain rerender all down to from the context provider works faster in this case. I have tried observedBits feature of react to learn what it does. I see that observedBits do not make any effect, because the root level state change causes full tree rerender.
|
Oh, yes. You are totally right. That's my bad.
Would you look into MobX and see how they solve the issues, or not? |
I have used Mobx previously and seen that their Observer triggers rerender
for every component where the state is used, regardless of what is being
used. Maybe it changed recently. That is why I asked the link to the Mobx
benchmark test to learn how they do it. Do you have this benchmark test
code for Mobx or not?
"Would you look into MobX and see how they solve the issues, or not?"
What do you mean? What would you like me to look at?
…On Fri, Aug 16, 2019 at 11:23 AM Daishi Kato ***@***.***> wrote:
It will not loose typing.
Oh, yes. You are totally right. That's my bad.
But it will have other disadvantages.
Would you look into MobX and see how they solve the issues, or not?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1?email_source=notifications&email_token=AA6JSVN4VOIBPQLFYZSQUT3QEXQORA5CNFSM4HZBGGMKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4NIEWI#issuecomment-521831001>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA6JSVNE3VOYLWDHETGJUOLQEXQORANCNFSM4HZBGGMA>
.
|
I personally didn't write any benchmark code for MobX. But, the point I'm raising is not about the render part, but the mutation part.
I didn't yet fully understand all "disadvantages" you mentioned. |
"... all "disadvantages" you mentioned. Wondered if it's solved in MobX or not." |
Thanks for the explanation. |
They tell here https://mobx-react.js.org/observer-hook: |
The reason I thought the benchmark target of your lib is MobX, is about mutations not renders. |
I have thought about putting the same large table performance demo using Mobx to compare, but I have not figured out how to achieve it with Mobx :) It seems like each table cell should be a consumer of the global state to make sure only the affected cells are rerendered, or there is another way? |
I'm willing to help to compare with react-tracked. 😄 |
"I'm willing to help to compare with react-tracked. 😄" |
Hi @dai-shi Hookstate now supports IE11 via |
I don’t read the code as I’m on vacation now, but do you deal with non-get proxy handlers? |
I provide custom proxy-polyfill which supports only get method needed for
the Hookstate core. It is as simple as:
```
function ProxyImpl(target, handler) {
this.target = target;
if (Array.isArray(target)) {
return target.map((e,i) => handler.get(target, i));
} else {
const result = {};
Object.keys(target).map(k => {
result[k] = handler.get(target, k)
})
return result;
}
}
```
"I don’t know anybody who would be interested in your lib with
proxy-polyfill" - you said you had requests for your library to work
without Proxy, so I though you captured this interest and connections. If
not it is ok. It was an exercise to see how much the hookstate needs to run
in IE11.
…On Tue, Aug 27, 2019 at 6:50 PM Daishi Kato ***@***.***> wrote:
I don’t read the code as I’m on vacation now, but do you deal with non-get
proxy handlers?
I don’t know anybody who would be interested in your lib with
proxy-polyfill. Sorry about that.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1?email_source=notifications&email_token=AA6JSVJRRHSP6FGYZG6K2FDQGTFDVA5CNFSM4HZBGGMKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD5GWCYI#issuecomment-525164897>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA6JSVN56EQ3BRNO6VHOIOLQGTFDVANCNFSM4HZBGGMA>
.
|
Interesting. So, you don’t use/need google lab’s proxy-polyfill. There was a general discussion whether proxy can be polyfilled for IE11 in the Redux community. |
Could you give me a link to this discussion?
…On Tue, 27 Aug 2019, 20:18 Daishi Kato, ***@***.***> wrote:
Interesting. So, you don’t use/need google lab’s proxy-polyfill.
There was a general discussion whether proxy can be polyfilled for IE11 in
the Redux community.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1?email_source=notifications&email_token=AA6JSVOK7QBL75ISX6SHWQTQGTPPDA5CNFSM4HZBGGMKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD5G5I5I#issuecomment-525194357>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA6JSVPPE5ETSOIC76YQRS3QGTPPDANCNFSM4HZBGGMA>
.
|
I don’t have the link right now, but it’s the long discussion about hooks. By the way, if you can implement your lib without proxies that easy, you wouldn’t need proxies from the start, would you? That might be simpler. |
Let’s continue the discussion in avkonst/hookstate#6 I will close this issue later as it becomes very long mostly discussing about hookstate. |
Copied the table in README. |
@bySabi Thanks for coming here. If there's a huge demand on a comparison table, I should probably start a new repo. Hm, that would not be a bad idea. I could add more columns to compare. Adding benchmarks would also be nice. BTW, your implementation of const forceUpdate = s => ~s; might have an issue with batched updates. |
@dai-shi thanks for take the time for look at the code. Please ping me when the new comparison repo is done. I also thought that |
I used to use Now, I use |
I imagine you don't have the link to the issue at hand :-)? ... I would like to try an issue repo
Now that I am looking at how to add Typescript support, I will probably update |
Let me see... dai-shi/reactive-react-redux#20 (comment) Here you go. |
Thanks for the link, they have been useful to understand the problem. Well, it seems that in my case the 'forceUpdater' Using
When I create Although surely there is something that escapes me. The code needs other hawk eyes :-) Thanks for your time. |
@bySabi Hi, I created a new repo. https://github.com/dai-shi/lets-compare-global-state-with-react-hooks |
@dai-shi It's a really interesting benchmark. I'm a React developer but I'm a beginner in terms of measuring performance. How did you make them ? How do you know which features to compute and how did you calculate them ? I want to know how to make a performance evaluation of a library or tools like that.
|
calculateChangedBits=0
observedBits
The text was updated successfully, but these errors were encountered: