Dynamically rendering components
My objective in a nutshell is making a small user card appear on an element hover, like on twitter. The way I'm making it is the following:
This is a barebones representation
And then I have a wrapper for this popup With this method I get the error:
'use' router primitives can be only used inside a Route.
which I guess is because I'm trying to create UserPopup
just in the air without a parent, but I'm not sure how I should be creating UserPopup
within a context, or do I just have to not use useAction
and find something else? The other problem with this is I'm getting the warnings computations created outside a createRoot or render will never be disposed
. So I tried using both render and mount and attach the UserPopup element I create directly to the element I want it to go in but nothing happened, this was my attempt:
So what is the right way to do this?13 Replies
Use Portal
I tried doing that like so:And the result I see is exactly the same as without portal
The issue seems to be me using useAction outside of any context, but idk how I could implement this tooltip functionality without creating components on the fly.
Is there a reason to set the element in activate though?
Also in this case, you aren't returning anything for the setElement
Yeah I copied the code wrong in my reply. It's setting it right in my code except the data fetching or anything reactive doesn't seem to work in the created component.
My goal is for the element to be created only on hover, and then be destroyed when the mouse leaves the hovered element.
Other options would be:
- Having one tooltip component created on page load, whose position and displayed data is changed. I could do this I guess but I'd have to implement refetching and calculating positions and stuff and it seems a little excessive, there's definitely a better way.
- Creating a separate tooltip component for each wrapper and then just using Show to hide them. I tried this and it resulted in a lot of flickering every time I hovered.
There are a lot of these wrappers present on the page at one time, and I also want them to refetch data when re-hovered.
And final reason is I guess I just want to learn how to create ephemeral components.
You could take a look at how Kobalte implements it if anything
Oh good idea. Thanks!
My biggest issue now is that creating components and then mounting them can leave them undestroyed and stuck in memory. ANd that's how all my modals, tooltips currently work...
using
Show
is probably your best option
I wonder what the flickering you mentioned is about 🤔
I'd probably have activate and deactive basically set a signal for showing and unshowingNVM I solved it by simply wrapping the Show in a Suspense
It's exactly what I did, and I just tried that again and had
a
Show when={active()}
where active
is a bool signal accessor and there was the component I wanted wrapped in this Show component, but every time I hover over the element, the whole page goes black for a split second and then the tooltip shows. However when the page goes black it also counts as a MouseLeave event and so the active
signal is set to false which causes another flicker, and since my mouse is still above the hoverable element the whole loop starts from the beginning.
Basically every time the when
changes everything goes black for a little bit.that is very weird
oh LOL
Why does that happen though? Tbf I don't understand and I just noticed everything under the closest suspense boundary was rerendering
Well if you're fetching data using a resource, the resource will trigger the nearest Suspense boundary
In this case, the nearest might have been the app level boundary
Right! Yes I am in fact using resource. Sorry for being dumb and thanks for the help.
No problem 🙂