primitives
primitives copied to clipboard
Slow performance of dialog compare to headless-ui
Bug report
Current Behavior
So till now I was using headless-ui dialog in my application. Everything was smooth on my iphone 8. Recently I decided to drop headless-ui in favor of radix-ui but endup with problems.
Previously (with headless-ui) time between clicking trigger and seeing dialog on the screen was closed to 0. It was instant. Currently (with radix-ui's dialog) it is more close to 1-2 seconds rather than 0.
I tested this with example from radix's documentation. (so content of dialog is quiet small). Tried it directly on radix's example page as well. There is noticeable delay as well but its more close to 0.5-1sec.
Is there anything going on with this component ?
Your environment
Software | Name(s) | Version |
---|---|---|
Radix Package(s) | react-dialog | 1.0.4 |
React | 18.1.0 | |
Browser | safari/brave | |
Assistive tech | ||
Node | n/a | |
npm/yarn | ||
Operating System | IOS |
May not be relevant to what you're working on - but got a fast response to this on twitter from shadcn. If you're using a backdrop blur (default in shadcn dialog), try checking that first. removed all delay for me https://twitter.com/tiniscule/status/1672619850508713986
@tiniscule to be honest I tried those things. It seems that others radix-ui components have similar issues e.g. dropdown menu.
It may be specific to this landing page - it is leaflet map w big number of markers, so memory heavy
It seems that framework like chakra-ui are quiet good in opening dropdowns/modals in such enviroment.
From some unknow reason radix-ui is really bad.
I'm having a similar issue with the "Select" component. I have an array of objects mapped out into components, each one of these items (like under 50 generally) has a 'select'. The performance is fine at rest. The problem is, the each of items mapped out (which contains a select component) is a 'droppable' container for dnd-kit. When I try to drag a draggable element over the items, performance absolutely tanks and we get 'stutter' (almost corresponding with the draggable element passing over an item). Removing the Radix select component fixes all issues and performance is buttery smooth as expected. Removing the modified Radix select component and placing the empty skeleton from the docs in it's place, has the same negative performance impact as the modified component, even though the empty Select doesn't have any items or logic beyond the component itself.
I assume this is more of a conflict rather than a Radix issue but I'm posting here because there is some Radix weirdness. When in the react dev tools, if you mouse over the Radix portal / context components that make up the "Select" elements the console gets spammed with CSS errors about width and height mostly (Some 'border-left, border-top' etc).
You guys have any ideas?
I might actually try headless (or just write my own with Floating UI) to see if I can avoid the issue.
Yeah, just tried a basic select menu with Floating UI, none of the problems I was experiencing with Radix.
I love radix and I've been using it everywhere, this is the first major issue I've encountered that wasn't a simple fix or something I can understand. Firefox's profiler throws 'jank' warnings with the Radix select corresponding to the dragging action if this is any help?
My issue seems there is a large vdom, but headlessui dose not have this problem. The performance test shows recaculation of style is too long in
Presence
component.
Is this being looked at? Any workarounds? This issue (recalculate style when calling getAnimationName) makes radix dialogs unusable in more complex apps.
The only method I currently use as a workaround is to set hidden class to all list items outside the viewport via IntersectionObserver, only reserve the size of the container for the item to avoid the layout shifting.
This way the DOM gets a much better performance when opening dialogs.
The downside of this way is that it is hard to reserve the size for complex items. Sometimes, I just simply hide all related items outside the viewport, and guess it, Chrome browser will handle it well! No layout shifting at all. But Safari dose not survive, you will get a stupid layout shift and that is why we still need a size reservation.
@Play-AV do you figure out how to handle the Select component performance issue. We face the similar performance hit when we have multiple Selection components inside an accordion. Each Selection contains 10 options, roughly 100 in total. It has a noticeable delay for an accordion to open up the tab, which I don't believe it's reasonable. It's there anyway I can lazy mount the Select content? but it seems like the display selected item also require to grab the styling from the option list, it looks like impossible to lazy because how the way Radix renders it.
@Play-AV do you figure out how to handle the Select component performance issue. We face the similar performance hit when we have multiple Selection components inside an accordion. Each Selection contains 10 options, roughly 100 in total. It has a noticeable delay for an accordion to open up the tab, which I don't believe it's reasonable. It's there anyway I can lazy mount the Select content? but it seems like the display selected item also require to grab the styling from the option list, it looks like impossible to lazy because how the way Radix renders it.
Honestly I just built my own Select. You can use Floating-UI and or React Aria as a really solid starting point, especially if your needs aren't hugely complex. I'd really like to revisit Radix eventually but this pushed me to explore some other options, as again my needs weren't complicated and I wanted to learn a little more. I'm pretty happy with some of the React Aria stuff and Floating-UI which I found because of Radix is excellent.
Same on my side, I switched to zagjs, which is way faster for dialog on mobile. Will happily switch back to radix when this issue is fixed.
👍 Unfortunately seeing this issue as well in my testing - I wonder if animationName
has to be a live-recalculated value, or whether we're actually just trying to cache the calculated values by running getComputedStyle
. I'm going to tinker with patching this method for my usecase.
These types of issues are difficult to tackle as they are heavily dependent on the scenario (ie. the page its on, size of the DOM, etc).
Is someone able to provide a sandbox that clearly demonstrates the issue?
I'll try to work on a sandbox today. Some of the perf issues are visible just on any logged-in page in val.town. We're getting bitten by the style calculation caused by Collapsible
Which costs 2 seconds on a logged-in pageload:
Opening dropdown menu on a large page takes 2+ seconds
Because of the bottleneck in presence.
Honestly, the bummer is that these bottlenecks all seem like they're in service of powering transitions, and we don't use appear/disappear transitions at all for any elements - and might try to patch away this code entirely because the tradeoff doesn't make sense.
Thanks, a sandbox would be a great start for us to start taking a deeper look.
Let's concentrate on a single issue rather than have lots of duplicates for the same thing: #1634
I have this problem when using shadcn. My options list consists of 1000+ items and it takes 3-4 seconds to open/close it on my macbook pro m1. I use shadcn throughout the project and would hate to use another ui library for one component. The native select works immediately