App Bridge, 1.27 useAppBridge()

I am trying to use the hook for App Bridge but it is blowing chunks because I don’t know. Please assist. So I load the useAppBridge. I then call it. I then try and use it. But the browser barks back at me this Uncaught Error. I was assuming the call to the hook useAppBridge, would return an App Bridge instance. Apparently, I was wrong. What is the deal here?

Uncaught Error: No AppBridge context provided. Your component must be wrapped in an AppBridge component.useAppBridge

useAppBridge.js:16

import { Provider, TitleBar, useAppBridge } from '@shopify/app-bridge-react';
import { getSessionToken } from '@shopify/app-bridge-utils';

const instance = axios.create();
export default instance;

function MyApp() {
  const [status, setStatus] = useState();
  const app = useAppBridge();
  instance.interceptors.request.use(
    function (config) {
      return getSessionToken(app)  // requires an App Bridge instance
        .then((token) => {
          config.headers['Authorization'] = `Bearer ${token}`;
          console.log("Token from callback ", token);
          return config;
        });
    }
  );

What happens when you try the sample that’s listed in the Shopify docs? https://shopify.dev/tools/app-bridge/react-components/provider

Specifically, this one sample. I’m still stuck in the Dark Ages using the Embedded App SDK and haven’t played much with the App Bridge SDK…

import React from 'react';
import {Provider, useAppBridge} from '@shopify/app-bridge-react';
function MyFunctionalComponent() {
  const app = useAppBridge();
  return (
    
      {(app) => {
        // Do something with App Bridge `app` instance...
        if (app) {
          app.getState().then((state) => console.log(state));
        }
        return Hello world!;
      }}
    

  );
};
function MyApp() {
  const config = {apiKey: '12345', shopOrigin: shopOrigin};
  return (
    
  );
}
const root = document.createElement('div');
document.body.appendChild(root);
ReactDOM.render(

That example fails. Shopify is sloppy in their examples BTW. As a brief explanation of that, note that they use a ReactDOM render call, but there is no import of ReactDOM. So that tells you how much care they took with this concept. Nearly none I suspect. So we need to be careful of copy and pasting their example code!!

Simply put. If I use an old school way of dealing with App Bridge, I do indeed get working code. For example, this code works:

import createApp from '@shopify/app-bridge';
window.app = createApp({
  apiKey: data.apiKey,
  shopOrigin: data.shopOrigin,
});
console.log("What is a window.app? ", window.app);

But this more modern code, supposedly in place, does not work. And that is what I am curious about.

import { Provider, TitleBar, useAppBridge } from '@shopify/app-bridge-react';
function MyApp() {
  const app = useAppBridge();
  console.log("And what is App from useAppBridge: ", app);

So in the one case, I get an App, in the other, errors.

Uncaught Error: No AppBridge context provided. Your component must be wrapped in an AppBridge component.

I would like to know why that is. Seems simple enough. I am frustrated because my App only works when I load it after installing it. The install flow is broken due to something internal at Shopify, and my App during install ends up OUTSIDE an iframe, likely because App Bridge.

Solved. Just had to ensure any call to useAppBridge() is in a component already a child of the Provider component, which instantiates App Bridge.

1 Like

@HunkyBill I still have an simular problem

I have this code for axios:

const instance = Axios.create();

instance.interceptors.request.use(function (config) {

return getSessionToken(window.app).then((token) => {

config.headers[“Authorization”] = Bearer ${token};

return config;

});

});

However that is thrwing the following error:

session-token.js?24e7:65 Uncaught (in promise) TypeError: Cannot read property ‘subscribe’ of undefined
at eval (session-token.js?24e7:65)
at new Promise ()
at eval (session-token.js?24e7:64)
at step (session-token.js?24e7:52)
at Object.eval [as next] (session-token.js?24e7:33)
at eval (session-token.js?24e7:27)
at new Promise ()
at __awaiter (session-token.js?24e7:23)
at getSessionToken (session-token.js?24e7:62)
at eval (install.js?9ca1:8)

On my _app I have component inside the Provider as you recommended.

function MyProvider(props) {
const app = useAppBridge();

const client = new ApolloClient({
fetch: authenticatedFetch(app),
fetchOptions: {
credentials: “include”,
},
});

const Component = props.Component;

return (

<Component {…props} />

);
}

class MyApp extends App {
render() {
const { Component, pageProps, shopOrigin } = this.props;
return (

<Provider
config={{
apiKey: API_KEY,
shopOrigin: shopOrigin,
forceRedirect: true,
}}

); } }

MyApp.getInitialProps = async ({ ctx }) => {
return {
shopOrigin: ctx.query.shop,
};
};

export default MyApp;

3 Likes

Did you find any solution to this? Just want to create a reusable axios instance, but don’t have window.app is undefined!

Pasting the updated code solution would be really helpful here.

AppBridge is now 2.0, and nothing I paste here would help. This issue is too old, and not relevant to the more modern App Bridge. That being said, I pointed out my error and how I fixed it.

thanks for your response, will open a new issue