leefsmp / Re-Flex

Resizable Flex layout container components for advanced React web applications
https://leefsmp.github.io/Re-Flex/index.html
MIT License
639 stars 72 forks source link

Performance issue in start resize #151

Closed Mattes-D closed 2 years ago

Mattes-D commented 2 years ago

Hi,

I'm using react-reflex to create a layout with several large tables. The tables need some time to render their style (about 2 seconds). I noticed that when the tables are rendered and I try to resize the layout, the whole UI is blocked for some seconds. It happens when I click the ReflexSplitter before any movement. I profiled the app and the root cause seems to be that ReflexContainer adds a the classes 'reflex-row-resize' or 'reflex-col-resize' to the body in ReflexContainer onStartResize. The change of the class name triggers an unnecessary layout cycle for the whole app. I removed the code that adds the classes and the initial lag is gone.

The classes are used to change the cursor. However, in my app the cursor correctly displays the resize cursors also without the global classes. Is this code really necessary?

Thanks for the help!

leefsmp commented 2 years ago

The reason the lib is changing the body class is because it usually happen that when dragging a splitter while resizing the mouse pointer is not exactly on top of the splitter element, hence if the cursor css is only applied to that element it causes a flickering as the cursor icon is intermittently being modified. That way it's constant during the drag.

It is surprising to me that your whole app is being rerendered as it is using directly DOM API and doesn't affect React props. I think a workaround would be to optimize your root component or some parent component (your table or higher in the hierarchy) to not rerender as their props is obviously not changed. If your table component is that heavy to render it is anyway a good initiative to optimize its rendering to the strict minimum.

Mattes-D commented 2 years ago

Thanks for the explanation @leefsmp, I didn't check what happens with the cursor during resize operation. I investigated the performance problems I have with my tables and was stumbling across the fact that clicking the ReflexSplitter without actually resizing already produces a lag of 2 seconds. The class names that are added to the body trigger a style recalculation of the whole app which are quite expensive in my case. I'm using Reflex to resize a layout with several tables so I can't avoid rendering the tables. Optimizing my table styles was not sufficient, but virtualizing the tables seems to do the trick.

leefsmp commented 2 years ago

I'm testing with this simple codepen and I can't reproduce the behavior you describe, resizing the splitter will not trigger a re-render of the containing component. The issue you are describing here seems to be specific to your project. If you can provide a testable minimal case that would be helpful.

leefsmp commented 2 years ago

closing as non-reproducible.