onMount called before elements are connected in outin mode
timothyallan opened this issue · 3 comments
I have a 3rd party component that relies on a document.getElementById
call to find a DOM node in my components onMount
function.
Works great with the normal transition, until I switch to an outIn
transition, then my components onMount
fires, but the DOM node doesn't exist yet, so the 3rd party component blows up.
I don't know exactly how it would look, but it would be great if there was a way to detect if the onMount
was actually mounted and the DOM was ready, or if the component is floating around outside of the DOM in the transitions pretend onMount
.
I still have to find a good solution to implement in the library, but this might be a good temporary workaround: https://stackblitz.com/edit/transition-group-out-in-onmount?file=src%2FApp.tsx
let onBeforeEnter: VoidFunction | undefined;
<Transition mode="outin" onBeforeEnter={() => onBeforeEnter!()}>
<Show>
{untrack(() => {
const [added, setAdded] = createSignal(!onBeforeEnter);
onBeforeEnter = () => setAdded(true);
// only render the actual content if added to the DOM
// unfortunatelly this needs <div> wrapper
return <div>{added() && <MyComponent />}</div>;
})}
</Show>
</Transition>
It may not be the nicest thing to wire up, but if done correctly, could work better then trying to patch every onMount
.
My other idea is to experiment with Suspense to defer the execution of effects... But maybe there is something simpler.
Here is the first solution abstracted to a component:
const TransitionChild: ParentComponent = props => {
const [added, setAdded] = createSignal(false);
useContext(TransitionCtx)(() => setAdded(true));
return <div>{added() && props.children}</div>;
};
// then in the App (or where you add your Transition)
const TransitionCtx = createContext<(cb: VoidFunction) => void>();
function App() {
let onBeforeEnter!: VoidFunction;
return (
<TransitionCtx.Provider value={cb => (onBeforeEnter = cb)}>
<Transition mode="outin" onBeforeEnter={() => onBeforeEnter()}>
{/* Any control-flow like Router, Outlet, Show, Switch, etc. */}
<Show>
{/* Needs to wrap every child */}
<TransitionChild>
{/* The actual element that will be transitioned */}
<div>Hello</div>
</TransitionChild>
</Show>
</Transition>
</TransitionCtx.Provider>
);
}
Transition with appear won't work if it has a outin mode parent Transition,