Multiple unnecessary re-renders
Hi there,
Frist off - I'm loving Sortly. I'm making use of it in a Meteor app I'm hacking together as a prof of concept.
One thing I'm having a problem with though. My itemRenderer renders multiple times, even with no prop changes and I was wondering if you could help cast a little light on things....
I've tried to use React.memo with a custom equal function, but even with that, and equal props, I still get the problem (I noted that in one of your examples, you used Reac.memo, and I'm assuming the same problem exists in that too).
I think it all comes down to the hooks. I'm using useDrag and useDrop hooks. I think they always return different functions, and therefore cause a re-render. Not sure if they need to work like this or if there is some tweak I can make to prevent it. I'm not massively familiar with React or even Javascript (part of the reason I'm making my app is to learn).
Any thoughts?
@robwheatley Could you post your replication code to somewhere like https://codesandbox.io/?
@robwheatley Could you post your replication code to somewhere like https://codesandbox.io/?
Thanks for the reply - Bit tricky because the data is fed from a Mongo DB and I'm using Meteor, but I will see what I can do when I'm back from my holidays in a few days. Hopefully I can replicate with a simplified version. If nothing else, making a simplified version may help me ID the problem myself.
@lytc Ah, I found a little time and knocked something together really quickly. It's a fork of your demo combined with a hack of one of your other demos. sandbox here
If you make a sort change and look at the console, you will see: "Tree Rendered" when that renders (once to initialise and again for each onChange) "container rendered: name" when each item container renders "container the same? bool name" each time a container is asked to re-render
As you change the sort, you can see that all item containers are asked to re-render, and even though the memo areEqual function returns true (the bool in the list above) the container still re-renders. I don't think they should (maybe I have all this wrong). With more hacking by removing the useDrag and useDrop hooks, the re-renders go away.
I hope all of that makes sense to you...
@robwheatley https://reactjs.org/docs/react-api.html#reactmemo
React.memo only checks for prop changes. If your function component wrapped in React.memo has a useState or useContext Hook in its implementation, it will still rerender when state or context change.
It rerender because of internal state change, isDragging for example!
But I wouldn't have thought that internal states would change on all items whenever they changed on one? I get that they would change on the one you are dragging and probably on the nearest neighbours too, but not on all the other items too. I must be missing something. Like I said in my intro, React and Javascript aren't my strongpoints.
My best guess at the moment is that the drag and drop (obtained from useDrag and useDrop) are functions and those functions are getting recreated each time something changes (a bit like when you do an in-line bind) forcing a re-render. Does that make any sense to you..?