I followed Shopify's guide, until the end of 4th step, to develop a Next JS app and I've setup two pages (embedded app navigation), Home and Page1. Now, when I click to open both pages, the app is doing a reload instead of routing...
You can see here the flickering issue - https://youtu.be/45RvYgxC7C0
Any help on this would be very appreciated.
_app.js
import React from "react";
import App from "next/app";
import Head from "next/head";
import { AppProvider } from "@shopify/polaris";
import { Provider } from "@shopify/app-bridge-react";
import Cookies from "js-cookie";
import "@shopify/polaris/dist/styles.css";
import "../css/styles.css";
import lang from "@shopify/polaris/locales/en.json";
export default class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
const config = { apiKey: API_KEY, shopOrigin: Cookies.get("shopOrigin"), forceRedirect: true };
return (
<React.Fragment>
<Head>
<title>My App</title>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="favicon.ico" />
</Head>
<Provider config={config}>
<AppProvider i18n={lang}>
<Component {...pageProps} />
</AppProvider>
</Provider>
</React.Fragment>
);
}
}
home.js
import React from "react";
import { Page, Layout, Card, FooterHelp, Link } from "@shopify/polaris";
export default function Home() {
return (
<Page title="Home">
<Layout>
<Layout.Section>
<Card title="Online store dashboard" sectioned>
<p>View a summary of your online store’s performance.</p>
</Card>
</Layout.Section>
<Layout.Section>
<FooterHelp>
Learn more about{" "}
<Link url="#" external>
our app
</Link>
</FooterHelp>
</Layout.Section>
</Layout>
</Page>
);
}
Page1.js
import React from "react";
import { Page, Layout, Card, FooterHelp, Link } from "@shopify/polaris";
export default function Page1() {
return (
<Page title="Page1">
<Layout>
<Layout.Section>
<Card title="Online store dashboard" sectioned>
<p>View a summary of your online store’s performance.</p>
</Card>
</Layout.Section>
<Layout.Section>
<FooterHelp>
Learn more about{" "}
<Link url="#" external>
our app
</Link>
</FooterHelp>
</Layout.Section>
</Layout>
</Page>
);
}
App generated with shopify CLI is extremely slow (due to ngrok and NextJS custom server, server side changes using the shopify official app take ages to reflect). Development experience is awful.
Shopify CLI is generating an app that does not work out of the box. App generated with shopify CLI is using old version of shopify node API and old version of all kind of dependencies (it still uses the koa-shopify-node-api dependency which is full of bug and being abandoned. Honest advice: stay away from this lib)
You can check out the Next.js GitHub repository – your feedback and contributions are welcome! The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js. Check out our Next.js deployment documentation for more details.
When using Shopify's app-bridge, it has a default behavior of navigating to a new route within the iframe that holds your app (and thus completely reloading the app), whereas React implements a client-side router.
Shopify doesn't provide a 100% plug-and-play solution for using client-side routing, but they do make it pretty easy with their ClientRouter component.
The examples on that page are for react-router, not Next.js's router, but the same idea applies to next/router.
For example, a simple router component could look like:
import {useEffect, useContext} from 'react';
import Router, { useRouter } from "next/router";
import { Context as AppBridgeContext } from "@shopify/app-bridge-react";
import { Redirect } from "@shopify/app-bridge/actions";
import { RoutePropagator as ShopifyRoutePropagator } from "@shopify/app-bridge-react";
const RoutePropagator = () => {
const router = useRouter();
const { route } = router;
const appBridge = React.useContext(AppBridgeContext);
// Subscribe to appBridge changes - captures appBridge urls
// and sends them to Next.js router. Use useEffect hook to
// load once when component mounted
useEffect(() => {
appBridge.subscribe(Redirect.Action.APP, ({ path }) => {
Router.push(path);
});
}, []);
return appBridge && route ? (
<ShopifyRoutePropagator location={route} app={appBridge} />
) : null;
}
export default RoutePropagator;
After creating that component, drop it in the _app.js file inside the Shopify routers, for example:
<Provider config={config}>
<AppProvider i18n={translations}>
<RoutePropagator />
<ApolloProvider client={client}>
// child components
</ApolloProvider>
</AppProvider>
</Provider>
When _app loads, it will now subscribe to changes from appBridge and let appBridge know to send a signal to the client rather than reload the entire iframe. If you apply any routing within the app, such as one page to another, it will also now update the browser's address bar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With