Update App bridge to Version 4
In this guide, we will talk about how to migrate our app from version 3 to version 4, first see Shopify guide here: Migrate your app to Shopify App Bridge React 4.x.x and App bridge official guide
Step 1: Add the app-bridge.js script tag
In the embed.html
and index.html
, update the content to:
<meta charset="UTF-8" />
<meta name="shopify-api-key" content="%VITE_SHOPIFY_API_KEY%" />
<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>YOUR APP NAME</title>
<link rel="manifest" href="/manifest.json" />
The Shopify API KEY will be inserted via vite, and the CDN link for the app bridge SDK remains the same
Step 2: Update the app bridge React to latest version
Go to the package.json
in the assets folder and update the version:
"@shopify/app-bridge": "^3.7.10",
"@shopify/app-bridge-react": "^4.1.5",
"@shopify/app-bridge-utils": "^3.5.1",
Step 3: Remove the Provider setup
Do just as in the Shopify guide, this step is quite simple.
Step 4: Update components
In this steps, beside all the already-in-the-guide stuff, we will only mention some other stuff that are not there.
You cannot show NavMenu in a page with Max Modal
If you show Nav Menu in the Max Modal, you will get an error like: Cannot get onHide of...
. For example, hide the
NavMenu
on page has Max Modal:
<>
{isNotBlogScreen && (
<NavMenu>
{appMenu()
.filter(menu => !['/feature-request'].includes(menu?.url))
.map(menu => {
return {...menu, destination: getUrl(menu?.url)};
})
.map(menu => (
// eslint-disable-next-line react/jsx-key
<ReactRouterLink url={menu.destination} rel={menu.rel || null}>
{menu.label}
</ReactRouterLink>
))}
</NavMenu>
)}
{children}
</>
);
Using Modal within Max Modal
In a complex editor like SEOon Blog app, we need to have Modal like Media
library upload modal inside the Max Modal. This will cause the the same problem as nesting the NavMenu
inside Max
Modal page. So you need to wrap the AppProvider
like [this](https://shopify.
dev/docs/api/app-bridge/using-modals-in-your-app#react-components-using-react-portals) to make it work.
No using the Contextual API inside the Max Modal
Use the Modal primary action and secondary instead of the Contextual API. Don't misuse it, or you get this error:
https://go.screenpal.com/watch/cZXq6onVZ7i
Try use src attribute of the modal
In some scenario, if your editor is a complex editor, leveraging third-party API, we need to use src
attribute for
your page, instead of inline your JSX inside the Max Modal content. See this guide
Just like in the SEOon blog, when we open a blog post, we open a Max Modal, open a new page, this page loads the app via route to the editor blog post. It will take a bit more time to load, but it prevent the problem of having many iframe within your Max Modal. See [this issue for reference](https://github. com/Shopify/shopify-app-bridge/issues/303) in which developers complaining about Max Modal mechanism.
Save bar inside Max Modal
If you apply for BFS with Max Modal and encounter something like this, well, you at the right place.
Correct this in your apps UI. See this screenshot for details. The Contextual Save Bar (CSB) has not been implemented correctly with the Max Modal. The proper way this should be displayed is when the form becomes dirty the Save and Discard button should appear in the TitleBar of Max Modal also removing the close button until a selection is made.
It is not stated in the Shopify App Bridge Documentation, but it can be done. Normally, using the SaveBar component will only appear on the top Shopify search bar. With the SaveBar implemented for the Max Modal, the close button of the modal will be hidden and it trigger leave prompts if you try to leave the page. All you need to do is to place the SaveBar component inside the Modal content.
import {Modal, TitleBar, useAppBridge} from '@shopify/app-bridge-react';
export function MyModal() {
const shopify = useAppBridge();
return (
<>
<button onClick={() => shopify.modal.show('my-modal')}>Open Modal</button>
<Modal id="my-modal" variant="max">
<div></div>
<TitleBar>
<button variant="primary">Primary action</button>
<button>Secondary action</button>
</TitleBar>
<SaveBar id="my-save-bar">
<button variant="primary" onClick={handleSave}></button>
<button onClick={handleDiscard}></button>
</SaveBar>
</Modal>
</>
);
}