Comments (88)
Just a note: based on facebook/react#14110 (comment), I ended up with the normal Redux subscriptions.
I'd probably need to do some benchmarks how slow this proxy approach is compared to react-redux.
from reactive-react-redux.
Let me try to run some performance tests. Could you share your benchmark as is?
from reactive-react-redux.
:nods: so, by removing concatenation (as long as it's a lazy operation nowadays) you are skyrocketing it yet again. Pretty sure - that's enough :)
from reactive-react-redux.
from reactive-react-redux.
@buzinas
Yes, it's tree-view-rher
. It's up-to-date. The result is of v0.9.1
.
Yes, v1.0.0
is supposed to be production ready.
It's interesting because I was just planning to do these before I got your comment.
- file a new issue for benchmark, and run it for
v1.0.0
again. - release
v1.1.0
today and run the benchmark.
from reactive-react-redux.
@dai-shi nope, sorry, has zero experience in this field) Just thought it might be interesting for you.
from reactive-react-redux.
@faceyspacey Thanks! I started this project with the mind that Redux should be easier for beginners, but you implied that it could be used in a broader way. That sounds exciting.
@theKashey already replied, but quoting his comment again, we are not yet ready for rest/spread.
I haven't thought much about it so far, but I will take some time to think about it as now it's clearer to me that rest/spread is important.
I don't know other unsupported edge cases at the moment, but I didn't obviously cover cases exhaustively.
from reactive-react-redux.
Meanwhile - rest
was a problem for mapStateToProps
realization, when you might want return/inject some slices from state as props.
With this approach, you are just "reading" from state inside component, as you wanted to do, and no need to rest.
const MyComponent = (props, state, actions) => ...
const MyComponentDestructured = (props, { foo } , actions) => ...
const RemixxComponent = (props) => {
const state = useReduxState();
const dispatch = useReduxDispatch();
return MyComponent(props, state, dispatch);
};
π?
from reactive-react-redux.
I use selectors, I love selectors for memoization, "scoping" and testability. And preparing a small update for reselect with WeakMaps and Hooks in mind.
Selectors ARE the API.
from reactive-react-redux.
Sounds like we should have a series of experiments. Another, not bad, option would be - useMemo
const MyRemixxComponent = (props, state, actions) => {
const val = state.mySelector(props)
const render = useMemo(() => <div>{val}</div>, [val]);
return render();
}
So - you will be able to bialout render by returning exactly the same return, and es-lint
(not babel, not proxy!) would help properly pass down all the props you need.
The memoization quality could be easily tested by Remixx, but calling a function twice.
from reactive-react-redux.
const wrapSelector = selector => {
const fn = (state, ...args) => selector(proxy(state), ...args);
fn.getAffected = proxy.getAffected.....
return fn;
}
const createSelector = (...args) => wrapSelector(realCreateSelector(...args));
@dai-shi - you may proxy proxied state. With some extension to your spread PR
one could disable tracking on the parent proxy while selector is working to make result more pure.
from reactive-react-redux.
yes, my friend, it's a chance for your work to be way bigger than something for "beginners" as you initially imagined it. And at the very least, it allows you to solve the selectors
issue, not just reducers. That makes your lib extremely powerful. Of course a redux fork must be used, but that's where the magic begins.
from reactive-react-redux.
@markerikson Thanks! I'll look into those discussion.
from reactive-react-redux.
@theKashey's proxyequal seems great. Let me try incorporating it.
from reactive-react-redux.
Works like a charm. Thanks tons, @theKashey.
from reactive-react-redux.
π π π
from reactive-react-redux.
A deadly simple React bindings library for Redux with Hooks API
Just wrote a short introductory article.
from reactive-react-redux.
I've been thinking a bit how this approach can be embeded in the official react-redux, but I'm not sure what would be appropriate.
but apparently there's a number of difficult edge cases.
Maybe, there's something I don't yet understand. There should be many edge cases, but what woud be the most critical ones?
from reactive-react-redux.
I would like to see some implementation details in the article.
Meanwhile:
- Why you need bailOut hack? It would be great to utilise React.memo. Actually I am not sure this is easy doable with hooks.
- You are not handling some edge cases, when you are reading not a POD type, an object for example, and passing it to another component. You have to βdeproxifyβ all the props in the result (you can do it inside bailouthack).
See https://github.com/theKashey/memoize-state/blob/master/src/call.js - You should pass a third argument to proxyState to maintain cross-render proxies-object red equality.
- Selectors, like reselect would be able to work properly after .3, but their memoization would break your one. Like you have 3 selectors, all reading different keys of a object. 2 got memorised and assessing only object, but one is not, and assessing the inner key - only that key would be in affected. 2 would partially fix it. I have a ongoing task for this a wrapper for memoization lib, which will replay the used keys in case of memozation.
The rest is awesome.
from reactive-react-redux.
article
I would like to write one when I got better understanding.
bailOutHack
The original motivation of mine is to avoid memoization (which I found is a rather hard concept for beginners).
After looking at facebook/react#14110, my hope is something like this library and I started experimenting it.
I may misunderstand something. What do you mean by utilising React.memo
?
I made a small example with useMemo
at https://github.com/dai-shi/react-hooks-global-state/blob/master/examples/11_deep/Person.tsx#L31-L43
Is it related at all? (BTW, this is another probject of mine with the similar motivation, but since it doesn't use Redux, there's nothing to do with this project.)
deproxify
Will look into it.
the third argument & reselect
Thanks. I'll try that.
from reactive-react-redux.
Probably the best way is not use use proxyState directly, but via memoize-state
, which will handle most of edge cases.
For you - just replace one line by another. See https://github.com/theKashey/beautiful-react-redux/blob/master/src/index.js#L64
from reactive-react-redux.
Thanks for your suggestion.
beautiful-react-redux
Wonderful. Solves the general problem I have in mind.
memoize-state
Starting reading the code.
third argument to proxyState
I got this one.
I woner if "deproxify" is needed if this ProxyMap is kept the same across rendering.
Like you have 3 selectors, all reading different keys of a object. 2 got memorised and assessing only object, but one is not, and assessing the inner key - only that key would be in affected.
Probably because I don't get this one yet. Maybe, I'd write a failing test to better understand the issue.
from reactive-react-redux.
const state = {
a: {
value: 1,
b: {
value1: 1
}
}
....
affected - a.value, b.value.
... memoize
affected - a, as long it maintain eq-ref all good.
... change a.value(changes also a), b is the same
affected - a.value, b
... you know - it would always fallback to the "root node", value of which would be changed due to immutability principles, and never miss the update. Just would be not as precise, as could.
So lets don't call it a problem, while it is not proven.
from reactive-react-redux.
Got that. Not a problem, but not as precise as it could be. Thanks.
from reactive-react-redux.
Well, I was trying twitter-lite benchmark (I don't think it's a good one for this comparison, though),
and found it just doesn't work probably because __proxyequal_scanEnd: "this is secure guard"
is enumerable. I need to learn more about this.
from reactive-react-redux.
secure guards
is a complex thing, and probably a mistake. And probably I should replace them by Symbols, to create a key non-enumerable by loops, but enumerable by spread.
The idea behind is to detect a full object spread and inform dev about deoptimization, or not to track all keys, as long one is tracking a whole object (this never was done).
For now you can disable it (globally) by calling spreadGuardsEnabled(false)
from reactive-react-redux.
@theKashey Thanks so much! It works.
from reactive-react-redux.
I run a benchmark using tree-view.
react-redux 5.0.7
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 50.73 β 9262.02 β 7520.57 β 576.89 β 1,52,51,54,52,43,49,47,48,56,53,50,47,57,49,51,50,57,49,53,54,47,52,54,52,50,42 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
react-hooks-easy-redux 0.8.0
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 8.37 β 28016.50 β 693.61 β 51.04 β 4,5,11,7,6,12,13,6,10,11,10,4,0,7,9,11,5,8,16,8 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββ
from reactive-react-redux.
As a comparison, this is a dumb implementation without any bindings, but just use useEffect
to subscribe the store and update for any changes.
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 29.62 β 22724.41 β 3248.64 β 224.59 β 22,28,27,30,26,29,31,34,27,26,25,29,23,29,30,27,38,35,33,34,24,27,36,31,22,36,33 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
from reactive-react-redux.
:noooooooooooo:
from reactive-react-redux.
No, something is wrong. When I run the dumb version in dev mode, it's almost freezing.
But in prod mode, it's faster. I'm not yet sure what's happening.
from reactive-react-redux.
I don't know why, but the dumb version in production mode is fast contradictory to the intuition. I'm curious about its optimization.
So far, what I found about proxyequal is that proxyState()
takes several milliseconds when an object is big. This can be seen to be fair because tree-view
is an extreme example. ...What's bothering is that the dumb version actually beats the proxy version.
from reactive-react-redux.
Probably I know that's the problem, and I know the way to solve it.
The Problem
You could not establish proxy upon frozen
object. That's why it clones it via Object.assign(it's slow).
https://github.com/theKashey/proxyequal/blob/master/src/index.js#L43
if (state.constructor.name === 'Object') {
const clone = Object.assign({}, state);
/// ^^ replace this by `const clone = {}`
Object.setPrototypeOf(clone, Object.getPrototypeOf(state));
return clone;
}
The solution
Set a prototype for an empty object, and override getOwnKeys to emulate key existence. Just enable spreadGuardsBack, or activate these 3 lines in another way.
Another solution
Detect frozen
object, and skip everything for plain ones.
@dai-shi - please monkey patch your version of proxyequal, and if it will help I'll ship a new version.
from reactive-react-redux.
I hope I don't misunderstand anything.
What I did: const clone = {};
if (true || shouldHookOwnKeys) { ... }
before (twice):
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββ€
β 6.63 β 28119.50 β 606.36 β 44.71 β 3,5,6,8,10,12,6,7,10,6,2,0,7,6,7,9,5 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββ
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββ€
β 7.00 β 28459.22 β 763.89 β 48.56 β 3,5,6,7,13,9,8,9,8,11,1,3,0,7,8,6,8,5,6,13 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββ
after (twice):
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 8.00 β 27645.82 β 877.30 β 70.92 β 1,6,9,13,11,7,9,8,3,5,9,7,4,10,8,5,10,9,10,7,5,9,12 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββ€
β 7.15 β 27425.04 β 902.62 β 63.44 β 1,4,9,7,8,11,4,8,6,9,10,2,3,6,5,8,6,11,8,10,8 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββ
Although my laptop may not be very stable while running, I see only a slight change.
Let me try a bit differently.
with spread guards:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββ€
β 6.47 β 28246.59 β 628.99 β 47.14 β 3,6,8,7,4,10,9,3,9,10,4,3,0,8,7,6,10,6 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββ
with spread guards + `const clone = {};`:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 6.71 β 27706.79 β 905.02 β 70.12 β 1,4,3,8,7,4,9,10,5,9,4,10,1,3,8,7,8,6,5,10,11,9 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββ
Not much difference? Hope these may help...
from reactive-react-redux.
Here you go:
git clone https://github.com/dai-shi/react-redux-benchmarks.git
cd react-redux-benchmarks
npm install
npm run initialize
REDUX=5.0.7 BENCHMARKS=tree-view:tree-view-rher:tree-view-dumb npm start
from reactive-react-redux.
Initial:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 6.44 β 28581.75 β 604.55 β 42.48 β 4,10,8,7,13,8,5,8,7,10,1,2,0,6,7,4,5,10,5 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββ
The problem was not in change tracking, but in the change comparison, to be more concrete in the building a list of keys to compare - collectValuables
, which uses search-trie
underneath.
I've run some perf tests and found a bit quicker solution to build trie(FPS 14), and get data I need from it(20)
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 19.20 β 22173.94 β 2957.29 β 223.88 β 4,8,17,22,19,15,10,14,22,24,21,18,28,22,10,21,18,22,9,17,24,25,19,24,18,33 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Still not awesome, but much better than before, as similar as dumb
tree:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 20.77 β 23343.37 β 3144.17 β 227.37 β 9,23,27,24,17,22,25,30,27,28,23,21,18,21,24,17,19,23,17,14,15,21,19,18,24,10,13 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
New version is published as 2.0.2. You may try on your machine.
PS: without proxyequal, with an update on every change, it gives 12FPS on my machine (MBP mid 2015)
from reactive-react-redux.
Great work. Let me try on my end.
with proxyequal v2.0.1:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 7.69 β 27448.93 β 674.92 β 47.62 β 3,7,9,10,8,13,7,8,13,8,3,0,7,8,7,9,6 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββ
with proxyequal v2.0.2:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 15.59 β 24285.89 β 2009.59 β 148.65 β 1,10,22,25,20,23,6,15,17,13,12,18,16,12,22,23,20,7,12,14,18,17,10,15,7,15,13,19 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Much better. (but, your perf test looks a bit better.)
PS: without proxyequal, with an update on every change, it gives 12FPS on my machine (MBP mid 2015)
How is this different from tree-view-dumb
?
from reactive-react-redux.
How is this different from tree-view-dumb?
19 vs 20 FPS
from reactive-react-redux.
Hm, my previous result was not really stable. Let me again run several times on my machine (MBP 2017).
tree-view-rher
: 21 FPS
tree-view-dumb
: 31 FPS
from reactive-react-redux.
@theKashey I happened to find // IE11 case
is faster on my machine in tree-view-rher
.
(A)
if (false && trie.edges.values) {
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 48.78 β 19296.74 β 21.64 β 16.24 β 1,48,54,46,47,48,54,49,45,43,46,49,43,54,47,52,49,41,52,56,43,54,48,53,45,55,45,51 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Does it make sense?
(edit) This gives an error when running, so there's probably something wrong.
(B)
I further tried to use an iterator returned by values()
directly, which results in like:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 30.38 β 22001.59 β 3016.81 β 209.17 β 1,24,38,36,14,28,34,37,23,42,22,27,36,25,17,28,34,24,34,41,30,38,25,23,43,28,19,30,38,43 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
(C)
Another trial is to use string.charCodeAt
and [[c, node], ...]
instead of Object.create()
in search-trie:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 45.37 β 18529.40 β 2281.47 β 95.50 β 1,41,46,43,48,33,51,55,41,46,39,55,47,46,40,51,40,55,37,42,51,50,35,43,45,51,48,46 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
However, this seems slower in dev mode.
combination of (B) and (C)
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 51.21 β 15174.46 β 2653.37 β 113.78 β 1,50,45,40,52,53,49,51,36,55,53,54,53,52,56,50,54,52,35,47,52,56,54,56,54,59,54,57,55 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
from reactive-react-redux.
π€―could you share the final solution?
I was thinking about removing trie completely, like
const buildTrie = lines => {
const values = new Set();
lines.forEach( line => {
const chunks = line.split('.');
chunks.pop(); // remove "last part"
chunks.reduce( (acc, name) => {
if(acc) {
acc = acc+'.'+name;
} else acc = name;
values.add(acc);
return acc;
}, '');
});
// return lines, which does not exists in the values
return lines.filter(line => !values.has(line))
}
from reactive-react-redux.
Here's the patch file against node_modules of the current final solution.
However, this seems slower in dev mode
Ah, it's also slow in prod mode in chrome. I wonder why the benchmark result seems good.
Anyway, this is not good. Let me see...
It was already slow in chrome even without this patch.
Could you try npx http-server runs/tree-view-rher
and npx http-server runs/tree-view-dumb
and see the difference by clicking "+" please?
from reactive-react-redux.
:nods:, I was thinking about flat arrays yesterday. Cool that you already spiked it and got so amazing results.
Meanwhile will try to see the difference
from reactive-react-redux.
According to this tests - https://jsperf.com/ltree-test/1 - the code with Set
, I posted above, is 2-3 times faster that your one.
Your one(arrays) is 25% faster than initial one, and the same with the "current" one for long strings, but faster on short ones.
from reactive-react-redux.
Good, jsperf is easier to test. (It's been a while since I last used it. It's now totally changed. Requiring GitHub oauth, and no fork?)
Played around a bit based on yours. https://jsperf.com/ltree-test-2/1
We might need the using part after putting for further experiments.
(BTW, I generally prefer array prototypes to for-loops, and I would avoid for-loops whenever possible in my application code...)
from reactive-react-redux.
πΏ Maps/Sets sucks. Arrays rule.
Probably hash mapping is far more expensive for short data, and in this case it always would be "short".
from reactive-react-redux.
Yeah, we might expect more optimizations by JS engines for maps and sets in the future, though.
from reactive-react-redux.
https://jsperf.com/ltree-test-2/5 - Set
degrades quickly with more and more data filled in.
Your variant just smashing it in Chrome. In Safari difference is just 10%.
from reactive-react-redux.
https://jsperf.com/ltree-test-2/9
Another trial, but it's not that compelling.
Well, more trial. This one is the best so far. https://jsperf.com/ltree-test-3
from reactive-react-redux.
Ah, it's also slow in prod mode in chrome. I wonder why the benchmark result seems good.
Anyway, this is not good. Let me see...
It seems fine now. I probably misunderstood something then.
from reactive-react-redux.
Re-running benchmarks with some variants.
Results for benchmark tree-view:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 51.71 β 9230.89 β 7516.19 β 569.54 β 1,55,48,53,51,47,48,51,52,53,44,55,52,53,52,48,54,56,57,47,53,55,54,53,50 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Results for benchmark tree-view-rher:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 19.71 β 24399.94 β 2165.48 β 152.65 β 1,15,22,28,23,16,12,21,20,22,23,17,31,25,18,15,18,19,20,17,9,18,27,17,12,13,33,14,27 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Results for benchmark tree-view-rher-simple:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 50.88 β 9568.31 β 7441.53 β 556.23 β 1,54,46,52,55,49,45,46,49,53,52,51,48,49,54,46,53,48,52,58,52,54,51,53,54,48,51 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Results for benchmark tree-view-memo:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49.14 β 15433.03 β 6133.68 β 432.18 β 1,45,54,37,52,55,44,43,51,46,51,54,41,52,53,45,50,49,51,47,43,53,42,54,55,49,53,57,50 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
tree-view
: the original one, react-redux 5.0.7
tree-view-rher
: useReduxState with proxyequal 2.0.2
tree-view-rher-simple
: useReduxStateSimple with shallow (limited) proxy
tree-view-memo
: pure useContext + useMemo approach
from reactive-react-redux.
So - the only bearable result is tree-view-rher-simple
. Is it usable in real applications, or too shallow?
from reactive-react-redux.
But, there's still room for improvements in proxyequal 2.0.2, no? I mean based on our trials in jsperf.
The shallow approach can be usable if developers carefully design the redux state with the shallow comparison in mind. This is probably too limited for the majority of redux use cases.
I'd still hope proxyequal to become comparable.
from reactive-react-redux.
Oh, I may mislead you that proxyequal 2.0.2 above includes the modification? Let me try that.
from reactive-react-redux.
Results for benchmark tree-view-rher with the patch:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 13.12 β 25649.44 β 1240.48 β 95.50 β 1,11,15,14,16,17,19,10,13,11,16,7,15,16,19,16,15,2,17,16,13,7,12,14,10,7 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Pretty sure I did something wrong... Could you check it?
diff2.txt
from reactive-react-redux.
It has to be the other way around like this. (I need your review @theKashey )
return lines.filter(function(x) { return values.indexOf(x) === -1; });
The new patch is: diff3.txt
Results for benchmark tree-view-rher with this new patch:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 40.07 β 17956.07 β 4275.31 β 303.62 β 1,35,50,30,39,44,41,47,30,42,34,24,44,40,42,48,41,40,44,46,26,44,48,41,38,43,36,37,43,45 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
(which may mean we can optimize more???)
from reactive-react-redux.
Just tried once again with diff.txt:
βββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 50.11 β 15180.51 β 2630.19 β 113.08 β 1,52,51,41,55,50,49,47,34,57,49,51,50,47,56,48,55,56,35,45,52,54,56,54,57,48,55,49 β
βββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
So, search-trie + patch still works better.
(edit) This patch (diff.txt) doesn't seem to make it work correctly, so the above result is void.
(edit2) I found a bug I created in diff.txt.
from reactive-react-redux.
:beautiful:
from reactive-react-redux.
@theKashey Are you available to update proxyequal some time soon like in a week or two?
Please let me know if you want me to work on a PR.
from reactive-react-redux.
I am back and active. Feel free to draft a PR in any time.
from reactive-react-redux.
Updated packages and run all benchmarks:
$ git clone https://github.com/dai-shi/react-redux-benchmarks.git
$ cd react-redux-benchmarks
$ npm install
$ npm run initialize
$ REDUX=5.0.7 BENCHMARKS=tree-view:tree-view-rher:tree-view-rher-simple:tree-view-memo:tree-view-dumb npm start
Running benchmark tree-view
react-redux version: 5.0.7
Checking max FPS... (30 seconds)
Running trace... (30 seconds)
Results for benchmark tree-view:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 51.61 β 9555.77 β 7210.61 β 548.58 β 1,51,53,50,52,46,47,48,47,56,51,55,46,54,51,53,50,52,53,57,53,55,52,50,54,53,54,53,49 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Running benchmark tree-view-rher
react-redux version: 5.0.7
Checking max FPS... (30 seconds)
Running trace... (30 seconds)
Results for benchmark tree-view-rher:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 38.96 β 17988.73 β 4321.41 β 303.09 β 2,36,47,30,40,42,40,50,33,41,31,22,43,37,41,48,45,37,43,39,27,45,37,39,43,37,33,45,40 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Running benchmark tree-view-rher-simple
react-redux version: 5.0.7
Checking max FPS... (30 seconds)
Running trace... (30 seconds)
Results for benchmark tree-view-rher-simple:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 51.61 β 9521.76 β 7253.08 β 549.60 β 1,52,43,51,56,49,48,45,52,53,58,53,48,44,55,52,50,56,54,56,53,54,53,49,53,55,52,53,48 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Running benchmark tree-view-memo
react-redux version: 5.0.7
Checking max FPS... (30 seconds)
Running trace... (30 seconds)
Results for benchmark tree-view-memo:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 50.04 β 15134.43 β 5632.15 β 412.14 β 42,55,43,53,54,47,45,43,51,44,53,52,50,49,46,56,47,49,48,47,53,49,55,57,47,53,55,50 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Running benchmark tree-view-dumb
react-redux version: 5.0.7
Checking max FPS... (30 seconds)
Running trace... (30 seconds)
Results for benchmark tree-view-dumb:
βββββββββββ¬ββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Version β Avg FPS β Scripting β Rendering β Painting β FPS Values β
βββββββββββΌββββββββββΌββββββββββββΌββββββββββββΌβββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5.0.7 β 28.71 β 22775.51 β 3256.32 β 228.11 β 1,23,34,29,34,32,38,27,25,23,28,24,32,25,26,32,28,32,26,23,28,37,27,21,35 β
βββββββββββ΄ββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
from reactive-react-redux.
@dai-shi : I'm a bit confused by the output there. It doesn't look like you're using the benchmarks repo the way I intended it to be used, which was to add multiple React-Redux builds into the react-redux-versions
folder, and run each of them against the same benchmark apps.
What are those results there actually comparing?
from reactive-react-redux.
@markerikson Sorry for the confusion. The first Version
column is meaningless. react-redux 5.0.7
is only used in the tree-view
benchmark and not in other tree-view-*
benchmarks. So, I'm comparing the original tree-view
with its variants tree-view-*
which I beleive provide the same functionality.
from reactive-react-redux.
That's what I was wondering, yeah.
Since I've only been seeing some of the comments in here, can you summarize what the actual changes have been, and what the perf results are?
from reactive-react-redux.
Well, originally I started this project because I wanted to pass down redux state directly in the context like react-redux v6, but as it's not yet possible with hooks, I ended up with putting redux store in the context like react-redux v5, for now.
Anyway, my interest then is to compare the proxy approach with react-redux v5 to see how proxy impacts on the performance. Just one benchmark case is not enough, but as a start, I picked tree-view
in your benchmarks.
There were lots of discussions and trials in the comments here (some of them are void because of my misunderstanding), but in the end we improved proxyequal
and the final results at the moment are the following.
tree-view
: ~51FPS (the original benchmark with react-redux 5.0.7)
tree-view-rher
: ~38FPS (react-hooks-easy-redux
with proxyequal
a.k.a deep proxy)
There are some other variants for comparison:
tree-view-rher-simple
: ~51FPS (react-hooks-easy-redux
without proxyequal
a.k.a shallow proxy)
tree-view-memo
: ~50FPS (just with hooks useContext
, useEffect
, useState
and useMemo
, no bindings library)
tree-view-dumb
: ~28FPS (with useContext
, useEffect
and useState
, updating all components)
BTW, I'm not sure if I understand other columns in the benchmark results: Scripting β Rendering β Painting β FPS Values
. Could you elaborate a bit on them? Or just if I should care them?
from reactive-react-redux.
The first three are the values that are recorded by the Chrome DevTools when you capture a performance trace. I'm not an expert on them, but to my understanding:
- "Scripting" is total time spent running JS
- "Rendering" is time spent doing page layout
- "Painting" is time spent actually drawing the updated layout on screen and/or GPU
The "FPS values" is what my benchmark script is recording, ie, what's used to calculate the average in the first column. The lib I'm using records any change in FPS. It's not perfect, because if you did a capture for 30 seconds, the first 20 seconds were 60 FPS, and the last 10 seconds were 30 FPS, then I think the current benchmark logic would count that as 45 FPS (just averaging the two values) rather than ( (20 * 60) + (10 * 30)) / 30
or whatever's needed to get a true average over time. But, it's sufficient for now.
from reactive-react-redux.
Thanks a lot!
from reactive-react-redux.
@dai-shi Two quick questions:
- If I install this package from npm, which of these examples above is it using now? I expect it to be
tree-view-rher
, but I only want to make sure if I'm correct. Are all performance improvements already up-to-date in npm? - Is this package ready for production?
from reactive-react-redux.
Let us continue the discusson about benchmarks in #3.
from reactive-react-redux.
Want to chip in this thread and mention that there is a new kid on the block https://github.com/cerebral/overmind/tree/next/packages/node_modules/proxy-state-tree
May be worth trying or borrow some ideas from it
from reactive-react-redux.
Hi @smashercosmo!
Looks interesting. How are you familiar with the library?
from reactive-react-redux.
That means one tree stops tracking when an other starts tracking. Since all component libraries produces their UI description synchronously, this gives a predictable behaviour.
That's something we talked about once. Having one tracker per state and switching it to different consumers. Probably it's not so dangerous. It's actually not a problem to trigger an error on track out of expected locations (ie async access), thus help customer detect a problem and wrap it with some method you may provide.
from reactive-react-redux.
It may not be dangerous if synchronous, but Iβm not sure how to implement it in a hook.
Havenβt yet read proxy-state-tree in detail, but I donβt get how to compare previous state and new one.
from reactive-react-redux.
Yeah, It's a bit complicated (and reactive) library. I am not sure it's interface would work for you.
from reactive-react-redux.
Meanwhile - @faceyspacey - you probably have something to say.
from reactive-react-redux.
there's a lot going on in this thread...i just wanna say im super impressed and very happy someone finally brought this to fruition. great work @dai-shi !!
The benchmarks are obviously of prime concern when it comes to this thing. If they can rival the old react-redux benchmarks, there's no reason this shouldn't become the de-facto way to use Redux.
An important goal for me in the past was the ability to continue to do deep key access checking when using the rest operator:
rest operator
const { someKey, ...rest } = someObject
<div>rest.someValue</div>
If you guys checked out Remixx from the Respond Framework you might have seen why this is important. Essentially the idea is that all component functions receive a 2nd argument for state
, which inevitably will be destructured most of the time, eg:
const MyComponent = (props, state, actions) => ...
const MyComponentDestructured = (props, { foo } , actions) => ...
NOTE: in Remixx, the goal is no visible usage of hooks nor
connect
; store access is completely built-in and transparent; it can be accomplished via several ways: fork of React or babel plugin that wraps all standard React components.
Not having rest is akin to the controversy around hooks requiring linting rules for the scenarios it doesn't support--i.e. "solutions" having such failed edge cases should be avoided at all costs.
@theKashey had mentioned the hurdles to this in the past. How are u guys viewing rest operator support now: a solid possibility that just needs to be pursued? or a road better not followed as the costs are too high? What are those costs? Any other edge cases that are currently not supported??
from reactive-react-redux.
So - still there is no solution for the rest spread, except...
We may actually create a super simple Babel plugin, which would transform rest opartor to the something digestible by us. One line before and one line after to toggle proxies on and off.
from reactive-react-redux.
I'm obviously not opposed to that. Are you 100% sure that's the only route?
from reactive-react-redux.
it's very nice to see you remembered the strategy; it's even nicer to see react-hooks-easy-redux
playing it's part perfectly (as in your sample implementation).
yea, on our side destructuring rest isn't a problem. it's only a problem for users that would expect to do so, as destructuring is so common with arguments.
both this and its "broader" use cases are exciting π. now we just gotta lockdown:
-
something for selectors: https://github.com/respond-framework/remixx/blob/master/docs/initial-plan.md#connect-implementation-5-selectors
-
something for redux modules: https://github.com/respond-framework/remixx/blob/master/docs/initial-plan.md#remixx-modules
...leaving modules out of the discussion for now, @theKashey what's your take on selectors? Do we need them, or is the work traditionally done in selectors now done in component functions like any other standard work? My initial idea was essentially preparing a complete and independent "UI Database" in the form of the combination of reducers + selectors. I've been away from Reactlandia for some time--what's your take?
from reactive-react-redux.
@theKashey , which is why I wanna make sure we pay special attention to selectors and truly get them right for the new proxy-based Redux world.
So, here's an example where the selectors API in this setup fails us:
const MyRemixxComponent = (props, state, actions) => {
const val = mySelector(state, props)
return <div>{val}</div>
}
const mySelector = memoize((state, props) => {
return state.temp === 'high' // low | medium | high
? state.highs // low and medium always returns mediums, therefore:
: state.mediums // POTENTIAL FOR UNNECESSARY RENDER
})
So react-hooks-easy-redux is only checking state. It's not making use of the intelligence within selectors, like react-redux does with HOCs.
How can we make the above not trigger unnecessary renders when state.temp
changes between medium
and low
??
My original idea for Remixx was to make the state
arg passed to your remixx components also have selectors built in, e.g:
const MyRemixxComponent = (props, state, actions) => {
const val = state.mySelector(props)
return <div>{val}</div>
}
on store creation, you pass reducers and selectors now, eg:
createStore(reducer, selectors)
And then somehow internally we produce a state
object that addresses this issue. Thoughts on how we might implement this??
from reactive-react-redux.
-
redux like
mapStateToProps
. A black box. But we could track what was used as inputs (property access), and what was returned. Like we know everything, and could bailout on shallow equal. But - we could return an array or an object, not just a POD type, and it may matter -
inline state access. We might track only the first part - property access, but not to bailout if you got the same result from different values. But! Usually, you will use POD types to create elements...
-
selectors. We might track what's happening inside
selector
, and we might track what it will return (that should be "our" selectors). This might create something like hierarchical cache - the first level (state access) determine shouldMyRemixxComponent
be called, while the second(selector result) may determine shouldMyRemixxComponent
return be rejected.
Plus - we have to hook into React.createElement, and track the factual usage. Including wrapping POD variables by object with defined [toPrimitive], thus track not the property access, but property read (only for numbers and strings :( )
from reactive-react-redux.
But we could track what was used as inputs (property access), and what was returned. Like we know everything, and could bailout on shallow equal.
that's what I was thinking.
And by having state.mySelectors
, during createStore
we have an opportunity to wire up the shallowEqual comparison of selector return values in order prevent component re-rendering.
In other words, we couple this to how re-rendering is currently prevented by react-hooks-easy-redux. It works to our advantage to have all our selectors up front. In fact, it's necessary (though we will to offer an API to add more via code-splitting).
This might create something like hierarchical cache - the first level (state access) determine should MyRemixxComponent be called, while the second(selector result) may determine should MyRemixxComponent return be rejected.
I guess this begins to more closely describe the implementation.
Plus - we have to hook into React.createElement, and track the factual usage
I guess here's where things get out of control--ur saying the most optimum version of selector tracking includes tracking usage of return values, not just shallowEqual of return value, correct?
Sounds like we have a roadmap??
from reactive-react-redux.
Es-lint can automatically discover all the values that go in the array like [val]
? I'm not sure what u r referring to that we get from es-lint??
But I love this idea! I guess we must parse all functions called on state
, and then take the return values and place them as deps to useMemo
. Is this what u have in mind?
It sounds like step 3 of the roadmap is maybe the easiest...perhaps this even addresses steps 1+2 (i.e. comparing return values to block additional rendering)!!
...actually, im wrong, it solves steps 1+2. But there's still a chance a value could be marked as a dep, but isn't in fact used in the jsx. So on top of this, we need to track access of selector-created objects.
I wonder if that much more tracking has potential to be less performant.
Either way, this is a great start! And in my opinion worthy of an initial release for the selectors feature. It's probably under 20% of the time that a dep is passed that isnt accessed. Maybe as low as 5%, what do u think??
from reactive-react-redux.
Es-lint can automatically discover all the values that go in the array like [val]? I'm not sure what u r referring to that we get from es-lint??
Cmon - React team created ESLint plugin to help you provide all the stuff you need for useEffect
and useMemo
. And also watches if you are using something you are NOT using :)
What about usage rate of selectors - it depends on code style. Sometimes it's π.
from reactive-react-redux.
Lol, have only been studying hooks, havent used em yet. ..In our case, it's kind of annoying that its an es-lint plugin, as we likely need our babel plugin to do the same work. Maybe you have a way to streamline building this I'm not aware of. I think we only wanna require our users to install a babel plugin.
Does it just provide warnings, or does it actually make the changes for you with eslint --fix
?
Unless somehow we get this for free as part of a standard babel plugin integration, i think we either gotta copy it or implement it ourselves, eg:
const MyRemixxComponent = (props, state, actions) => {
const val = state.mySelector('MyRemixComponent', props) // component name injected by babel plugin
return <div>{val}</div>
}
And then the hierarchical cache compares cached values for this precise component and makes final decision of whether to trigger re-rendering.
Also, since their could be multiple MyRemixComponent
, i guess we have to use useRef
or something like this to get a handle on particular component instances. Eg:
const MyRemixxComponent = (props, state, actions) => {
const ref = useRef(null)
const val1 = state.mySelector1(ref, props)
const val2 = state.mySelector2(ref, props)
return <div>{val1}, {val2}</div>
}
Then our algo operates on a structure like:
const refs = {
[ref]: [returnVal1, returnVal2], // compare these to return values in next potential rendering
[ref2]: [returnVal2_1, returnVal2_2]
}
I feel like in the end it will be best to use our own internal infrastructure, i.e. the infrastructure that react-hooks-easy-redux is using. It's often better to reduce the # of dependencies on outside things.
from reactive-react-redux.
yep, something like this.
from reactive-react-redux.
(I'm getting to understand what you guys are trying to do.)
from reactive-react-redux.
We had very nice discussions here. I appreciate for all who participated. Sine it got long, let me close this issue now. Please discuss in more specific existing issues or file a new issue.
from reactive-react-redux.
Related Issues (20)
- Component not aware of state change? HOT 29
- Try new proxyequal HOT 19
- Stale props issue in selector API HOT 10
- Question: Ease of gradual transition to hooks concern HOT 3
- Add comparison with react-redux v7.1 in README
- Benchmarking with cocktails app by mikeyhogarth HOT 5
- Why calculateChangedBits = () => 0 HOT 16
- Discussions about proxy-polyfill HOT 1
- Benchmarking state usage tracking and other related projects HOT 5
- "Please use <Provider store={...}>..." exception unable to track down root cause HOT 3
- 'Please use <TrackedState...>' exception. Need help! HOT 6
- useTrackedState on an array does not trigger a rerender of FlatList with the extraData prop HOT 4
- Question about re-evaluation strategy HOT 9
- False negatives in tracking with React.memo
- A new API for reverting proxy
- Discussion: Antipattern to recommend `useTrackedSelector` HOT 4
- Testing Environment Slowdown HOT 4
- getUntrackedObject always returning null HOT 3
- SSR and `useLayoutEffect` issues warning in dev mode HOT 2
- Why is "patchStore" not exporte? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from reactive-react-redux.