S
SolidJSgabriel

How can I only set the ref for an element once it's been inserted into the DOM?

I've tried a few things but it doesn't seem like the element is inserted to the DOM at the point where the ref is called, which does make a bit of sense, but I just can't find a proper escape hatch for this. Tried: - Using setTimeout(..., 0) before setting - Checking if document.contains(...) before setting - Using a hacky Mutation observer, not sure if I did my best on this one but doesn't seem optimal For background, my use case is wit using https://github.com/lxsmnsyc/solid-floating-ui/tree/main (from @lxsmnsyc ). The issue seems to happen when floating-ui itself tries to resolve the parent nodes for the floating element which do not exist at the point where the element hasn't yet been inserted in the DOM.
GitHub
GitHub - lxsmnsyc/solid-floating-ui: SolidJS bindings for Floating UI
SolidJS bindings for Floating UI. Contribute to lxsmnsyc/solid-floating-ui development by creating an account on GitHub.
G
gabriel40d ago
Someone else also seems to run into this https://github.com/lxsmnsyc/solid-floating-ui/issues/6
R
REEEEE40d ago
How are you setting the ref? I would suggest using a signal ref if you're not already
G
gabriel40d ago
yup, doing that doing it pretty conventionally, so something like:
const [ref, setRef] = createSignal();

return <Show ...>
<div ref={setRef}>...</div>
</Show>;
const [ref, setRef] = createSignal();

return <Show ...>
<div ref={setRef}>...</div>
</Show>;
I do have a mergeRef from @solid-primitives/refs though but I don't think it would make much of a difference
R
REEEEE40d ago
Hmm, could be a bug possibly
G
gabriel40d ago
pretty sure something could be done inside solid-floating-ui that could get around this, like making sure that the element has been inserted not sure how to get to that reactively with Solid though, I can only think of having a MutationObserver
O
Otonashi40d ago
elements are not mounted when ref is called, they are only mounted after the ref function is called, in the effect phase (unless you created the element without mounting it immediately i.e. outside the return; don't do that), which is when the floating-ui integration tries to get them the problem is probably that you have it in a Show that's gone from showing to not showing, so the element isn't mounted the preferred solution is to set the ref to null/undefined when the Show goes to false if it isn't working on initial render then it's possible something further up is creating the element without actually mounting it other than suspense
G
gabriel40d ago
hmm yeah don't think that's it, logging the state that goes into the when prop on a render effect doesn't only logs once though the ref callback does get called twice apparently tried doing that but it seems like it still errors I'll try getting a reproduction out
L
lxsmnsyc40d ago
there's not much to touch in solid-floating-ui though
G
gabriel40d ago
Gabriel Miranda
StackBlitz
Reproduction of issue with solid-floating-ui - StackBlitz
A Solid TypeScript project based on @floating-ui/dom, solid-floating-ui, solid-js, solid-transition-group, typescript, vite, vite-plugin-solid and csstype
G
gabriel40d ago
wasn't able to add a ErrorBoundary to this so the error only appears only in the console for some reason you just need to click the button hmm, so how what do you recommend I do to avoid this kind of thing?
O
Otonashi40d ago
- <Popover anchor={button} visible={visible()}>
+ <Popover anchor={button()} visible={visible()}>
- <Popover anchor={button} visible={visible()}>
+ <Popover anchor={button()} visible={visible()}>
fixes the issue in the repro
G
gabriel40d ago
oh missed the parenthesis , then I think it might be something else than what I've thought on second thought I think this might be the issue here
O
Otonashi40d ago
this sounds like you're calling props.children twice somewhere which would cause this if one of them was being discarded
G
gabriel40d ago
hmm yeah I actually kind of am
G
gabriel40d ago
here
No description
O
Otonashi40d ago
yes don't do that
G
gabriel40d ago
What's another way to do this, like on a createMemo with an on?
O
Otonashi40d ago
if you must, use the children helper
const c = children(() => props.children);
...
{typeof c() === "function" ? c()(Option) : c()}
const c = children(() => props.children);
...
{typeof c() === "function" ? c()(Option) : c()}
though if for some reason what you're doing there somehow works the same way in dev and prod (it doesn't if hmr still adds the extra accessor), you could do
{(() => {const c = props.children; return typeof c === "function" ? c(Option) : c})()}
{(() => {const c = props.children; return typeof c === "function" ? c(Option) : c})()}
G
gabriel40d ago
yeah I'll try doing this, using children ended up needing too much type finagling
O
Otonashi40d ago
it probably works, but i can't really say it's robust
const getChildren = children(() => props.children);
...
{(() => {const c = getChildren(); return typeof c === "function" ? c(Option) : c})()}
const getChildren = children(() => props.children);
...
{(() => {const c = getChildren(); return typeof c === "function" ? c(Option) : c})()}
would be better well that might complain about too many args
G
gabriel40d ago
yeah, the refs being called multiple times was that, and now its gone, but the show was actually going back and forth as you mentioned LOL
O
Otonashi40d ago
so it was both then
G
gabriel40d ago
yeah, I was too stubborn thank you so much for your time man, helped me a ton
Want results from more Discord servers?
Add your server
More Posts
Intersection Observer IssuesI'm working on a game and I want some elements to animate in when they become visible, so I'm using what write so as not to constantly write a redirect in every function in case of unauthorizeI dont have a database on the solidstart server, I only work with third-party APIs. Where to store Solid doesn't re-render when update the same array in createSignalExpected behavior: Re-render inputs every time passwords array is updated even with the same value,For some reason <select> doesn't work correctlyhttps://playground.solidjs.com/anonymous/eedf65f3-e52b-49b0-a8b2-513465a75666 Here it is. When changCan someone tell me how to redirect the user on each API, if 401, that is, do not write the logic agCan someone tell me how to redirect the user on each API, if 401, that is, do not write the logic agHow to use web component in solidjsPlease ask solidjs how to solve the use of web component component editor ts reported error PropertyHow do I debug updatesI thought My app is working fine except I noticed a lag, which performance profile shows lots of unnHow to detect button holding in solid js?Does anyone know how to detect a button being holding for 2 seconds and are there any libraries or bVite internal server error expected "}" but found end of filesee screenshot, this is not the end of the file (not even close)How do I "curry" a function with props?I have a method "colorize" that receives two arguments: hue and shade. A component has a props.hue aMobX + SolidJS enableExternalSource untracked bug?I am evaluating using MobX with SolidJS and now that there is an `untrack` parameter to `enableExterhow to efficiently make nested data structures in solidHello, I am new to Solid atm, but am aware of some reactivity principles like singals, memos, effectSolidStart - Nitro Module missing `context` keys in `request`Hey guys, I understand what I am asking about is likely out of scope, as this is dealing with a 3rHandle user interactions to send backendI would like to know what are methods that can handle identification of user interaction points likeHow do I use solid for reactivity without a build step?I like solid as a frontend library, and I want to use it as a "vanilla" state management library foruse directive typescript errorWhen i try to use the use: directive i get the error ```Type '{ type: string; placeholder: string; vI have to fetch initial information in a component, how do I do it?const App: Component = () => { const resp = await fetch(...); // show Home component after fDynamically creating resources based on reactive state in Solid Store**What would be the right approach to solve this using solids reactivity? ** I want to achieve the Struggling to understand the correct way to use createResource with a storeI have a global store `export const [dataStore, setDataStore] = createStore({ some: "data"}) `, whicHow do I "protect" routes? I am using @solidjs/routerNow that Outlet is not supported anymore? How do I implement a route guard for nested routes?