Skip to content
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

Add plugin to optimise rerender of arrays/objects when keys are added/removed #51

Open
SirJayEarn opened this issue May 6, 2020 · 7 comments
Labels
enhancement New feature or request hookstate-5 Features postponed for v5 plugin An issue affects a plugin

Comments

@SirJayEarn
Copy link

SirJayEarn commented May 6, 2020

Hi,

first of all thanks for this awesome library!

I intend to use this with a pretty big nested array. Updating an existing element only triggers re-renders on this element and it's children. Nice! But when adding a new element all the sibling elements are re-rendering even though they did not change. This can also be seen in the demo for complex tree structure.
I looked into the mutate plugin but it doesn't seem to get me where I want to go either.

Is there a way to only trigger re-renders for the one element that gets added, or for the element that gets removed and it's the following siblings? Can nested.map somehow be memoized?

Edit: Looks like I just found the solution. Using reacts own memo function seems to do the trick. If anybody is interested I can create a small example. If not this question can be removed

@avkonst
Copy link
Owner

avkonst commented May 7, 2020

Hi,

The answer is yes and no.

React compares before and after virtual DOMs and takes the action by removing or adding DOM elements. This can not be avoided, as react needs to have full arrays of components for comparison. So, if you insert an element to an array and it is mapped to a React component during rendering, eg 'tr', full table re-rendering is inevitable.

However, there are tricks which could allow to bypass this with a bit of change in Hookstate. The trick would be to use an object instead of an array, to avoid using Object.keys() calls, to delete an item by setting it to None value, to insert an item into a partition of a indexes range (this would allow to rerender only a partition, but not the whole array). I wanted to write a plugin for this (to support smooth infinite scroll additions), but it was not very much important for me. What is your usecase? How critical is it?

@avkonst
Copy link
Owner

avkonst commented May 7, 2020

If you sibling component is wrapped by React.memo full array rendering is still taking place, it just becomes quicker for sibling components. You need to be careful: the second parameter for memo function should be proper chain of properties being compared. If your array is array of strings, it is fine. If it is an array of objects, you might need to do equality check of it's properties which are used inside of the memoized component. You can not pass StateLink variable to the second argument of memo.

@avkonst
Copy link
Owner

avkonst commented May 7, 2020

Yes, I would be interested in to see you code sample

@SirJayEarn
Copy link
Author

This is the solution I came up with so far: https://codesandbox.io/s/new-shape-tofno?file=/src/App.tsx

using a combination of StateMemo and React.memo. I tried to avoid as much boilerplate as possible and therefore tried to avoid using a comparer function.
I tried using objects, but I think using Object.keys was what I was doing wrong. Using the object-approach sounds good, but also sounds like making code harder to maintain. Having a plugin for that would be awesome I think!

@avkonst
Copy link
Owner

avkonst commented May 12, 2020

What you are doing does not scale very well. Hookstate does the job (figuring out if it should rerender or not) on any state update for EACH hook placed. You are placing a hook for each element in the arrays. This is not the same as scoped state hooks. scoped state hooks scale to arrays with millions of elements (I checked it). I will keep this ticket as a reference to come up with the prlugin mentioned above, but it will take a while as there are other more important tasks at this stage.

@avkonst avkonst added the enhancement New feature or request label May 12, 2020
@avkonst avkonst changed the title Question: Array optimization Add plugin to optimise rerender of arrays/objects when keys are added/removed May 12, 2020
@avkonst
Copy link
Owner

avkonst commented May 12, 2020

Ref: #14

@avkonst avkonst added the plugin An issue affects a plugin label May 26, 2020
@avkonst
Copy link
Owner

avkonst commented May 28, 2022

Need to check how much this issue is relevant with React 18

@avkonst avkonst added the hookstate-5 Features postponed for v5 label Dec 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request hookstate-5 Features postponed for v5 plugin An issue affects a plugin
Projects
None yet
Development

No branches or pull requests

2 participants