Background:
I am trying to create some links in my embedded Shopify app.
I understand that I cannot use the simple <a> tag due to the fact that Shopify embedded apps are rendered as iframes.
I made some headway with this tutorial, but I am stuck: https://theunlikelydeveloper.com/shopify-app-bridge-react-router/
What I am trying to do:
I have 3 pages (index.js, dashboard.js, and support.js). I would like to allow the user to navigate from one page to another (with links and/or buttons).
My Code:
By following the tutorial above, I've gotten this far:
// index.js
import { Page, Frame } from "@shopify/polaris";
const Index = () => {
return (
<Page>
<Frame>
{/* LINK TO DASHBOARD PAGE*/}
{/* LINK TO SUPPORT PAGE */}
</Frame>
</Page>
);
};
export default Index;
// routes.js
import React from "react";
import { Switch, Route, withRouter } from "react-router";
import { ClientRouter, RoutePropagator } from "@shopify/app-bridge-react";
function Routes(props) {
const { history, location } = props;
return (
<>
<ClientRouter history={history} />
<RoutePropagator location={location} />
<Switch>
<Route path="/dashboard">
<Dashboard />
</Route>
<Route path="/support">
<Support />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</>
);
}
export default withRouter(Routes);
// link.js
import React from "react";
import { Link as ReactRouterLink } from "react-router";
const IS_EXTERNAL_LINK_REGEX = /^(?:[a-z][a-z\d+.-]*:|\/\/)/;
function Link({ children, url = "", external, ref, ...rest }) {
if (external || IS_EXTERNAL_LINK_REGEX.test(url)) {
rest.target = "_blank";
rest.rel = "noopener noreferrer";
return (
<a href={url} {...rest}>
{children}
</a>
);
}
return (
<ReactRouterLink to={url} {...rest}>
{children}
</ReactRouterLink>
);
}
export default Link;
Additional:
I believe I'm supposed to implement the following code somewhere, but I don't see how it fits into the picture of navigating between pages with a link or button.
<AppProvider linkComponent={Link}>
{/* App content including your <Route> components */}
</AppProvider>
At this time of building embedded app you can make client-side navigation using app-bridge utilities as referred to in this answer
You just need to edit _app file and consider making client-side navigation from your components(can't use a normal Link)
import {useEffect} from 'react';
import Router, { useRouter } from "next/router";
import { RoutePropagator as ShopifyRoutePropagator } from "@shopify/app-bridge-react";
function RoutePropagator () {
const router = useRouter();
const { route } = router;
const app= useAppBridge();
useEffect(() => {
app.subscribe(Redirect.Action.APP, ({ path }) => {
Router.push(path);
});
}, []);
return app && route ? (
<ShopifyRoutePropagator location={route} />
) : null;
}
Then use this component in your _app file
_app.tsx
class MyApp extends App {
render() {
const { Component, pageProps, host } = this.props as any;
return (
<PolarisProvider i18n={translations}>
<ShopifyBridgeProvider
config={{
apiKey: API_KEY,
host,
forceRedirect: true,
}}
>
<RoutePropagator />
<ApolloClientProvider Component={Component} {...pageProps} />
</ShopifyBridgeProvider>
</PolarisProvider>
);
}
}
Now you've subscribed for routing events in _app file, we just require to make client-side navigation right in your pages
import {useAppBridge} from '@shopify/app-bridge-react';
import { Redirect } from '@shopify/app-bridge/actions';
function IndexPage(props) {
const app = useAppBridge();
return (
<>
<div>{'you are in main page'}</div>
<div onClick={() => {
app.dispatch(Redirect.toApp({
path: '/dashboard'
}));
}}>
{'to dashboard'}
</div>
</>
);
}
And for going back to the main page / route, I've found that it trigger an oauth again if not provided with the shop name, so we will use the shop query params for that
<div onClick={() => {
app.dispatch(Redirect.toApp({
path: '/?shop=<shop-name>.myshopify.com'
}));
}}>
{'to main'}
</div>
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