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

Is this a React SPA reliant on React Router being loaded by a Next JS server? #64

Open
laurencefass opened this issue Jul 5, 2024 · 4 comments

Comments

@laurencefass
Copy link

laurencefass commented Jul 5, 2024

I found this looking for a mobile theme for my nextjs site. Please forgive my ignorance in making my assumptions but Im trying to better understand the routing in this app and to understand the level of integration with Next app routing.

It looks like its loading everything on the client and using React Router. From my initial experiments I dont think IonApp is compatible with layout files as it needs to load on the client, making ionic reliant on react-router. Is this effectively a CRA React SPA being using Next for initial page load?

The root of this project seems to demonstate the reliance on client side loading.

import dynamic from 'next/dynamic';

const App = dynamic(() => import('../components/AppShell'), {
  ssr: false,
});

export default function Page() {
  return <App />;
}

Possible I am misunderstanding but the fact that IonApp needs to be rendered on the client makes Ionic components and Next JS fundamentally incompatible unless using it only to deliver SPA using React Router.

My initial conclusion (Id love to be provied wrong) is that I think Ionic may be designed for SPA not for partial page renders.

Thanks

@laurencefass
Copy link
Author

laurencefass commented Jul 5, 2024

Related Ionic forum post

Add first class support to @ionic/react for Next JS SSR + Partial page pre-rendering: ionic-team/ionic-framework#29690

@laurencefass laurencefass changed the title Is this a CRA React SPA being loaded by a Next JS server? Is this a React SPA reliant on React Router being loaded by a Next JS server? Jul 5, 2024
@nathanchapman
Copy link
Collaborator

Hey @laurencefass!
You're correct that Ionic currently relies on react-router and is not compatible with the router provided by Next.js
Capacitor also requires a static bundle and thus, can only handle CSR. This means Next.js needs to run in export mode to generate the bundle for use with Capacitor.
This still allows you to use a single codebase between web and native mobile, but only have SSR capabilities on web. Once the issue you linked is resolved, this will greatly simplify the routing requirements, e.g. you'd no longer need distinct (and likely duplicative) routers between web and mobile.
Hope this helps!

@laurencefass
Copy link
Author

laurencefass commented Jul 9, 2024

Progress!

I have successfully integrated Ionic component library with Next JS app router (Im using 14.something) without having installed React-Router or IonicReactRouter using the Provider pattern ReduxToolkit uses to share context between client components.

I can navigate from the IonMenu via Next/Links and use (seemingly) any Ionic components in my Next app routed client components.

The crux of the solution was to create a client-side IonAppProvider and wrap {children} in my root layout.

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body>
          <IonAppProvider>
            {children}
          </IonAppProvider>
      </body>
    </html>
  );
}

and the IonAppProvider looks something like this (note its a client component)

'use client'
...
imports etc
...
export function IonAppProvider({ children }: { children: React.ReactNode }) {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  return <>
    {isClient && <IonApp key={Math.random()}>
      <IonNextMenu />
      <IonPage>
        <IonHeader>
          <IonToolbar className="custom-toolbar">
            <IonTitle>NextJS and Ionic Page routing layout</IonTitle>
          </IonToolbar>
        </IonHeader>
        <IonContent id="main-content" className="ion-padding">
          <IonHeader>
            <IonToolbar>
              <IonButtons slot="start">
                <IonMenuButton />
              </IonButtons>
              <IonTitle>Menu</IonTitle>
            </IonToolbar>
          </IonHeader>
          <div className="page">
            {children}
          </div>
        </IonContent >
      </IonPage>
    </IonApp>}
  </>
}

This sets up Next app routing and pages "just load" from <Link>s

Note: The IonNextMenu is an IonMenu wrapper that registers callbacks on <Link> clicks to close the menu at the right time. The close animation just appears to work.

Now we can write pages without thought to the IonicApp.... Next pages now just become "normal" pages.

export function Page() {
  return <p>this is Next page wrapped in an IonicApp->Page layout.

Of course if one needs to override the root layout, one can just create multiple root layouts...

@laurencefass
Copy link
Author

laurencefass commented Jul 9, 2024

Nested layouts also work and you can use server components but any components containing Ionic stuff need to be 'use client' (for now).

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

2 participants