Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onMount called before elements are connected in outin mode #34

Open
timothyallan opened this issue Mar 22, 2023 · 3 comments
Open

onMount called before elements are connected in outin mode #34

timothyallan opened this issue Mar 22, 2023 · 3 comments

Comments

@timothyallan
Copy link

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.

@timothyallan
Copy link
Author

Just to add another use case: any forms using Felte, and its <ValidationMessage/> component will die when used inside a transition using outIn, as it looks for the the closest form element on mount... which doesn't exist.

Screen Shot 2023-03-22 at 4 45 58 PM

@thetarnav
Copy link
Member

thetarnav commented Mar 27, 2023

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>
  );
}

@thetarnav thetarnav changed the title Detecting an 'actual' component mount or a transitional mount onMount called before elements are connected in outin mode May 4, 2023
@Huodoo
Copy link

Huodoo commented Dec 7, 2023

Transition with appear won't work if it has a outin mode parent Transition,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants