Questions and discussions about using the Shopify CLI and Shopify-built libraries.
I am using NextJS to do dynamic routing.
My file is called
[itemId].js
Although to do dynamic routing, you need to specify getStaticPaths and getStaticProps.
The minute I specify those, AppBridge throws an error.
AppBridgeError: APP::ERROR::INVALID_CONFIG: host must be provided
I have tried to specifically adding host in both getStaticPaths and getStaticProps but it still asks to provide it.
Below I have provided how those functions work, I just have a random value for host to not share it.
export const getStaticPaths = async (ctx) => {
return {
paths: [{ params: { itemId: "1", host: 'myhost' }}],
fallback: 'blocking',
}
}
export async function getStaticProps(data) {
return {
props: {itemId: "1", host: 'myhost'
}
}
}
Any help on getting dynamic routing working would be appreciated with some code examples if there are.
Thank you.
Solved! Go to the solution
This is an accepted solution.
Yup. I had that as well. I fixed that in my RoutePropagator. Can't remember what part exactly solved it, but here's what I have.
In _app.tsx I have:
<PolarisProvider>
<AppBridgeProvider config={config}>
<RoutePropagator />
<ApolloProvider state={storedParams?.state}>
<Component {...pageProps} />
</ApolloProvider>
</AppBridgeProvider>
</PolarisProvider>
And then this is my full RoutePropagator:
import { useContext, useEffect } from "react";
import Router, { useRouter } from "next/router";
import { Context as AppBridgeContext, RoutePropagator as ShopifyRoutePropagator } from "@shopify/app-bridge-react";
import { Redirect } from "@shopify/app-bridge/actions";
function RoutePropagator() {
const router = useRouter();
const { route, asPath }: { route: string, asPath: string } = router;
const appBridge: any = useContext( AppBridgeContext );
useEffect( () => {
appBridge.subscribe( Redirect.Action.APP, ( payload: any ) => {
Router.push( payload.path );
} );
}, [appBridge] );
return appBridge && route ? (
//@ts-ignore
<ShopifyRoutePropagator location={asPath} app={appBridge} />
) : null;
}
export default RoutePropagator;
I believe it was the `useEffect()` that fixed it where I push the payload.path into the router when listening (.subscribe()) to app navigation events in appbridge.
I believe your error is unrelated to your `getStaticPaths` functions. It would also happen if you'd have any other routing.
It is going wrong wherever you have this line of code:
<AppBridgeProvider config={config}>
Where `config` is:
const config = {
apiKey: process.env.NEXT_PUBLIC_SHOPIFY_API_PUBLIC_KEY,
forceRedirect: true,
shopOrigin,
host
};
The host is undefined. I've seen more people mention this, but `host` is not always returned by Shopify in the URL.
I've had to get a bit creative to solve this.
First I create an object of all the params from the url. If `host` is a part of that, I use that.
If that is not the case I check if `shop` is part of the params, because `host` is actually the `shop` but base64 encoded. I stumbled upon that little bit of information by pure luck. I did `btoa( shop )` and it worked and hasn't failed me yet so it must be true.
If `shop` also isn't part of the params, I just pluck it out of the start of the URL. I can't remember at the moment if it should be the full "shop-slug.myshopify.com" part or just what becomes before the ".myshopify.com" part: "shop-slug", but you can get there by trial and error.
So it would look something like this:
// get params from url
const params = getSearchParams( window.location.search );
let host;
if ( params?.host ) {
host = params.host;
} else if ( params?.shop ) {
host = btoa( params.shop );
} else {
host = btoa( /* get from url manually */ );
}
I hope this helps.
Thanks for your help. I feel like I am getting closer.
One other issue that came up, now since the host displays, the url changes though
if I visit /items/item/1 for example, everything loads up, but then the URL changes to:
/items/item/[itemId] ... any idea on this?
This is an accepted solution.
Yup. I had that as well. I fixed that in my RoutePropagator. Can't remember what part exactly solved it, but here's what I have.
In _app.tsx I have:
<PolarisProvider>
<AppBridgeProvider config={config}>
<RoutePropagator />
<ApolloProvider state={storedParams?.state}>
<Component {...pageProps} />
</ApolloProvider>
</AppBridgeProvider>
</PolarisProvider>
And then this is my full RoutePropagator:
import { useContext, useEffect } from "react";
import Router, { useRouter } from "next/router";
import { Context as AppBridgeContext, RoutePropagator as ShopifyRoutePropagator } from "@shopify/app-bridge-react";
import { Redirect } from "@shopify/app-bridge/actions";
function RoutePropagator() {
const router = useRouter();
const { route, asPath }: { route: string, asPath: string } = router;
const appBridge: any = useContext( AppBridgeContext );
useEffect( () => {
appBridge.subscribe( Redirect.Action.APP, ( payload: any ) => {
Router.push( payload.path );
} );
}, [appBridge] );
return appBridge && route ? (
//@ts-ignore
<ShopifyRoutePropagator location={asPath} app={appBridge} />
) : null;
}
export default RoutePropagator;
I believe it was the `useEffect()` that fixed it where I push the payload.path into the router when listening (.subscribe()) to app navigation events in appbridge.
Thank you! I am getting
TypeError : Cannot read properties of null (reading 'subscribe') from the useEffect() hook, I will do some investigations and let you know
appBridge is undefined then. Do you have the dependency installed correctly?
These are the AppBridge related ones that I have:
"@shopify/app-bridge": "^2.0.4",
"@shopify/app-bridge-react": "^2.0.4",
"@shopify/app-bridge-utils": "^2.0.4",
If you have, running another `npm install` often works for me with stuff like this.
I was missing
@Shopify/app-bridge
Installed it, removed node_modules and ran npm i again.
I also had the
Everything seems to be working! URL paths don't change change now to [itemId]. Thanks so much 🙂
You saved my day! So grateful.