ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.06k stars 13.51k forks source link

bug: ion-loading doesn't wait for page transition to finish before dismissing #24292

Open milanharia opened 2 years ago

milanharia commented 2 years ago

Prerequisites

Describe the Feature Request

I would like some guidance on how to incorporate React Suspense into an Ionic React project.

Describe the Use Case

When using React Suspense to suspend the loading of the contents of a page, I run into an issue where the page's transition breaks since there is no IonContent in the mounted page. Once the suspense resolves and the IonContent is mounted, the animation then works correctly. This is not an issue for pages that do not have a footer, since the entire suspense wrapper could be wrapped with an IonContent as below:

<IonContent>    
    <React.Suspense fallback={<IonLoading isOpen={true} />}>
        {RandomComponent ? <User1 /> : <User2 />}
    </React.Suspense>
</IonContent>

The issue then arises when you have a page that has an IonFooter since this sits outside the IonContent wrapper so you cannot wrap the suspended component in an IonContent.

To demonstrate this problem in more detail please check out this demonstration: https://codesandbox.io/s/nostalgic-platform-qfwqv

Describe Preferred Solution

Preferably, there would be a component which is able to wrap the IonContent and IonFooter so that the entire page content can be suspended and lazy-loaded such as the solution below:

Page.tsx

const PageContent = React.lazy(() => (import('./PageContent')))

function Page {
    return (
        <IonPage>
            <IonHeader>
                ...
            </IonHeader>
            <NEWCONTENTWRAPPER>
                <React.Suspense fallback={<IonLoading isOpen={true} />}>
                     {<PageContent /> }
                </React.Suspense>
            </NEWCONTENTWRAPPER>
    )
}

PageContent.tsx

<>
    <IonContent>
        ...
    </IonContent>
    <IonFooter>
        ...
    </IonFooter>
</>

I am open to any other alternatives you have to solve this issue.

Describe Alternatives

No response

Related Code

No response

Additional Information

No response

averyjohnston commented 2 years ago

Thanks for the request. Could you try wrapping your IonLoading component in another IonContent and see if that solves your issue?

<React.Suspense fallback={<IonContent><IonLoading isOpen={true} /></IonContent>}>
  {GetDataAndDecideWhichComponentToRender ? <State1 /> : <State2 />}
</React.Suspense>
milanharia commented 2 years ago

@amandaesmith3 thank you for the response. We initially tried this approach but we ran into issues where the suspense would resolve during the page transition animation resulting in a glitching effect, especially on iOS. This demonstrates the issue in more detail: https://codesandbox.io/s/elated-surf-ydlpf

Doing this also introduces a glitch on ios when the parent page uses a collapsable large title. If you directly route to a nested page and then click the back button to go back to the parent page (e.g. /user/user1 > /user), the title animation seems to break.

averyjohnston commented 2 years ago

For the suspense resolving during the animation, this is technically working as intended (the async process finishes before the transition, and the IonLoading component only shows for that long), but I think we can smooth it out a little. I'll work on it and let you know when I have more to share. For a workaround in the meantime, you could try adding showBackdrop={false} to the IonLoading to reduce the flicker somewhat.

As for the collapsible large title issue, could you provide steps to reproduce? I'm unable to reproduce in my end; here's a recording showing what I'm doing along with the code I added to your example: https://user-images.githubusercontent.com/90629384/144481423-5acdb77d-45d7-4a76-9594-0922acc03d45.mp4

milanharia commented 2 years ago

If you go to the /users/1 route directly (i.e. refresh the page on /users/1) and then press the back button, you then get transitioned back to the /users route as expected, however, if you watch the title animation you can see it go below where it is supposed to sit and then suddenly jump back up to the correct position.

averyjohnston commented 2 years ago

I'm still unable to reproduce; could you perhaps give a recording showing the behavior you're seeing, along with the code needed?

jsoneaday commented 2 years ago

Does this thread mean that Ionic 6 is working correctly with Suspense and there is nothing to fix?

averyjohnston commented 2 years ago

Does this thread mean that Ionic 6 is working correctly with Suspense and there is nothing to fix?

Technically, yes, but the visual effect from the original poster's example here could be smoothed out a little from Ionic's side. Namely, we could stand to wait for the page transition to finish before dismissing the ion-loading component, which would reduce the visual flicker.

I'm going to go ahead and change this ticket to cover that update. In the meantime, @milanharia if you are still having trouble with the title animation, could you file a separate issue with its own code reproduction?

bernhard-buss commented 2 years ago

Hello,

Any update on this issue?

We are also running into this, using a simple IonSpinner to indicate loading of a lazy sub page with suspense, but when the page code (bundle) is ready, the spinner disappears and the old page reappears and the new page is fading in. This looks very bad. It should not show the old page but directly show the new one. Is there any way that we can let Ionic know about being inside Suspense setup and thus adapt the fading in?