I'm not positive if the Toast, Loading, and ContextualSaveBar are supposed to be available to embedded apps (i.e., don't require a Frame), but the Toast is mentioned as a replacement to the showFlashMessage API from the EASDK so I assumed it would be. All of these components complain about not having a frame, but their code seems to indicate they should work in the App Bridge.
Utilizing the Toast, Loading, or ContextualSaveBar components results in them displaying.
The following error is shown in the console:
index.js:1452 Warning: Failed context type: The context `frame` is marked as required in `WithProvider`, but its value is `undefined`.
in WithProvider (at src/index.js:50)
in div (created by Page)
in div (created by Page)
in Page (created by WithProvider)
in WithProvider (at src/index.js:49)
in div (created by ThemeProvider)
in ThemeProvider (created by AppProvider)
in AppProvider (at src/index.js:48)
index.js:1452 Warning: Failed context type: The context `frame` is marked as required in `Toast`, but its value is `undefined`.
in Toast (created by WithProvider)
in WithProvider (at src/index.js:50)
in div (created by Page)
in div (created by Page)
in Page (created by WithProvider)
in WithProvider (at src/index.js:49)
in div (created by ThemeProvider)
in ThemeProvider (created by AppProvider)
in AppProvider (at src/index.js:48)
import React, { Component } from 'react';
import { AppProvider, Page, Toast } from '@shopify/polaris';
const SHOPIFY_APP_KEY = '**YOUR_APP_KEY_HERE**';
export default App extends Component {
render() {
return (
<AppProvider apiKey={SHOPIFY_APP_KEY} forceRedirect>
<Page>
<Toast content="Hello" onDismiss={() => console.log('Dismissed')} />
</Page>
</AppProvider>
);
}
}
Similar code when using the Loading or ContextualSaveBar produces the same error. Other components such as Modal and ResourcePicker are working fine for me. I'm fairly certain the bridge is available to our app, as our app has the new Navigation bar configuration in our partner portal.
Hey @mbaumbach thanks for the issue – Loading and Toast are meant to be used with embedded apps and replace the EASDK methods easdk.startLoading(), easdk.stopLoading(), and easdk.showFlashNotice(). ContextualSaveBar is not available for embedded apps.
The 5 components which delegate to the Shopify App Bridge are Page, Modal, Loading, Toast, and ResourcePicker (also listed here https://polaris.shopify.com/guides/designing-apps#section-decide-when-polaris-is-right-for-your-app).
I will take a look at the issue, but if the Shopify App Bridge authenticates properly the mount lifecycles for Toast and Loading delegate to app bridge and should not throw this frame error.
Aside from the issue, we do need to make it clear if a component like ContextualSaveBar is not available for use with an embedded app. I opened an issue for this #593.
Thanks for the clarification @tmlayton! I thought the ContexualSaveBar might be non-embedded only. Let me know if I can provide any additional assistance debugging here.
@mbaumbach in the meantime if you are blocked, you can pull the appBridge instance from context and follow the Shopify App Bridge docs on how to use Toast (formerly known as Flash) and Loading.
Thanks for the workaround! I'm just beginning to adopt Polaris 3 for our apps, so not in any rush at the moment. I will say moving from 2.12 to 3 was a cinch and we're excited to take advantage of some of the new components. 👍
Glad to hear! And I have confirmed this is an issue and have been able to reproduce. We will work on getting a fix out next week.
@mbaumbach after digging in a bit more it looks like Loading is working fine, but will just log a console error which causes no harm other than noise. We will get this fixed.
In the meantime, to suppress the noise you can use childContextTypes and getChildContext to set a mocked frame. React’s legacy context docs say "Don’t do [this]", but it is fine in this case as frame is never updated nor used.
This example will set a mocked frame for MyExamplePage’s subtree:
// This example assumes the app is embedded,
// app provider is already initialized, and
// app provider wraps this example page component
class MyExamplePage extends React.Component {
static childContextTypes = {
frame: PropTypes.object
};
getChildContext() {
return {frame: {}};
}
render() {
return (
<Page title="Example page">
{/* Will start the loading bar and should not log an error */}
<Loading />
</Page>
);
}
}
It is a similar situation for <Toast /> where the console error does not prevent it from working, but for <Toast /> is actually not working. And to make it more confusing the logged error is not related 😄
For <Toast />, it appears to be an issue with the Shopify App Bridge host, and not in Polaris. I have raised an issue with their team in https://github.com/Shopify/app-bridge/issues/537 (private repo).
Thanks @tmlayton! I thought I may have seen the Loading bar flicker in at one point, but also thought I may have been seeing things and then got distracted by the error in the console. :)
Yes, that console error is very distracting! It took be a bit before I noticed the loading bar was actually working as well.
@mbaumbach Toast not displaying has been fixed and I opened a separate issue for the error messages #611
Thanks @tmlayton, seems to be working for me now!
Looks like this is still an issue. I'm using polaris 4.0.0. The solution is to wrap the page in a frame component. Would be nice if we didn't have to do this.
<Provider config={config}>
<AppProvider i18n={[]}>
<Frame>
<Page title="">
<Toast
content="Successfully updated"
onDismiss={() => setShowToast(false)}
/>
</Page>
</Frame>
</AppProvider>
</Provider>
Thank you for sharing this workaround. I just encountered the same error. The Shopify App Bridge Toast component seems like too much for such a trivial thing like showing a message. I continue to use the Polaris Toast.
Most helpful comment
Looks like this is still an issue. I'm using polaris 4.0.0. The solution is to wrap the page in a frame component. Would be nice if we didn't have to do this.