Solved

App Bridge, 1.27 useAppBridge()

HunkyBill
Shopify Expert
4845 60 547

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 <Context> 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;
        });
    }
  );

 

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
Accepted Solution (1)
HunkyBill
Shopify Expert
4845 60 547

This is an accepted solution.

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

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com

View solution in original post

Replies 8 (8)

Gregarican
Shopify Partner
1033 86 285

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 (
    <div>
      {(app) => {
        // Do something with App Bridge `app` instance...
        if (app) {
          app.getState().then((state) => console.log(state));
        }
        return <span>Hello world!</span>;
      }}
    </div>
  );
};
function MyApp() {
  const config = {apiKey: '12345', shopOrigin: shopOrigin};
  return (
    <Provider config={config}>
      <MyFunctionalComponent />
    </Provider>
  );
}
const root = document.createElement('div');
document.body.appendChild(root);
ReactDOM.render(<MyApp />, root);

 

HunkyBill
Shopify Expert
4845 60 547

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 <Context> 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.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
HunkyBill
Shopify Expert
4845 60 547

This is an accepted solution.

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

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
leesaapp
Shopify Partner
2 0 0

Pasting the updated code solution would be really helpful here.

Leesa - Analyse all your data in one dashboard - https://leesaapp.com/
HunkyBill
Shopify Expert
4845 60 547

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.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
leesaapp
Shopify Partner
2 0 0

thanks for your response, will open a new issue

Leesa - Analyse all your data in one dashboard - https://leesaapp.com/
Icarus_
Tourist
7 0 3

@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 (<anonymous>)
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 (<anonymous>)
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 (
<ApolloProvider client={client}>
<Component {...props} />
</ApolloProvider>
);
}

class MyApp extends App {
render() {
const { Component, pageProps, shopOrigin } = this.props;
return (
<AppProvider i18n={translations}>
<Provider
config={{
apiKey: API_KEY,
shopOrigin: shopOrigin,
forceRedirect: true,
}}
>
<ClientRouter />
<MyProvider
Component={Component}
{...pageProps}
shopOrigin={shopOrigin}
/>
</Provider>
</AppProvider>
);
}
}

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

export default MyApp;
sagar_at_avyya
Shopify Partner
31 1 16

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


Sagar @ Avyya - Modern Sales Booster
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution