Join us for an upcoming Shopify Partner webinar on February 27, 2024. Discover the latest Checkout Extensibility features, and deep dive on improvements to Shopify Functions and Web Pixels. Register now for either the 10am EST or 2pm EST sessions.
Solved

How to use app bridge with my own redux store ?

barisozdogan
Visitor
2 0 0

Hello,

I've setup my shopify app by following build a shopify app with node and react tutorial.

Currently my _app.js file is;

import App from 'next/app';
import Head from 'next/head';
import { AppProvider } from '@shopify/polaris';
import { Provider } from '@shopify/app-bridge-react';
import '@shopify/polaris/dist/styles.css';
import translations from '@shopify/polaris/locales/en.json';
import Cookies from 'js-cookie';
import ClientRouter from '../components/ClientRouter';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';

const client = new ApolloClient({
    fetchOptions: {
        credentials: 'include'
    },
});

class MyApp extends App {
    render() {
        const { Component, pageProps } = this.props;
        const config = { apiKey: API_KEY, shopOrigin: Cookies.get("shopOrigin"), forceRedirect: true };
        return (
            <React.Fragment>
                <Head>
                    <title>Sample App</title>
                    <meta charSet="utf-8" />
             
                </Head>
                <Provider config={config}>
                    <ClientRouter />
                    <AppProvider i18n={translations}>
                        <ApolloProvider client={client}>
                            <Component {...pageProps} />
                        </ApolloProvider>
                    </AppProvider>
                </Provider>
            </React.Fragment>
        );
    }
}

export default MyApp;

 

The problem is I don't know exactly how can i create my own redux store for my own components (not the ones mentioned here app bridge actions) and as well as how can i attach my react-redux Provider component to that store while still relying on app bridge?

Which Provider should cover other -> app-bridge-react Provider or react-redux Provider ?

I believe i should somehow create my own actions for my custom components and should be able to dispatch them through my own part of redux store just like pre-defined actions in app bridge.

I've been looking for this answer for almost a decade but unfortunately I was not able to find any proper example on the web nor under the shopify app developments tutorials.

Could you please help me on this ?

Thanks,

Accepted Solution (1)

Trish_Ta
Shopify Staff
58 13 27

This is an accepted solution.

Hi  

Hope this helps!


Trish

Trish | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

View solution in original post

Replies 2 (2)

Trish_Ta
Shopify Staff
58 13 27

This is an accepted solution.

Hi  

Hope this helps!


Trish

Trish | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

mattfrancis888
Shopify Partner
4 0 0

EDIT: Nevermind! I was looking at the wrong redux-store in my redux dev tools!

Hi Bari,

How were you able to solve your situation? 

My code:

 

import React from "react";
import App from "next/app";
import Head from "next/head";
import { AppProvider } from "@shopify/polaris";
import { Provider, Context } from "@shopify/app-bridge-react";
import { authenticatedFetch } from "@shopify/app-bridge-utils";
import "@shopify/polaris/dist/styles.css";
import "../css/main.css";
import translations from "@shopify/polaris/locales/en.json";
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import { Provider as ReduxProvider } from "react-redux";
import { store } from "../store";

function userLoggedInFetch(app) {
    const fetchFunction = authenticatedFetch(app);

    return async (uri, options) => {
        console.log("URI", uri);
        const response = await fetchFunction(uri, options);

        if (
            response.headers.get(
                "X-Shopify-API-Request-Failure-Reauthorize"
            ) === "1"
        ) {
            const authUrlHeader = response.headers.get(
                "X-Shopify-API-Request-Failure-Reauthorize-Url"
            );

            const redirect = Redirect.create(app);
            redirect.dispatch(Redirect.Action.APP, authUrlHeader || `/auth`);
            return null;
        }

        return response;
    };
}

class MyProvider extends React.Component {
    static contextType = Context;

    render() {
        const app = this.context;

        const client = new ApolloClient({
            // fetch: authenticatedFetch(app),

            fetch: userLoggedInFetch(app),
            fetchOptions: {
                credentials: "include",
            },
        });

        return (
            <ApolloProvider client={client}>
                <ReduxProvider store={store}>
                    {this.props.children}
                </ReduxProvider>
            </ApolloProvider>
        );
    }
}

class MyApp extends App {
    render() {
        const { Component, pageProps, shopOrigin } = this.props;
        const config = { apiKey: API_KEY, shopOrigin, forceRedirect: true };
        return (
            <React.Fragment>
                <Head>
                    <title>Sample App</title>
                    <meta charSet="utf-8" />
                </Head>

                <Provider config={config}>
                    <AppProvider i18n={translations}>
                        <MyProvider>
                            <Component {...pageProps} />
                        </MyProvider>
                    </AppProvider>
                </Provider>
            </React.Fragment>
        );
    }
}

MyApp.getInitialProps = async ({ ctx }) => {
    return {
        shopOrigin: ctx.query.shop,
        API_KEY: process.env.SHOPIFY_API_KEY,
        host: process.env.SHOPIFY_APP_URL,
    };
};

export default MyApp;

 

 

 

import { createStore, applyMiddleware, combineReducers } from "redux";
import { shopifyReducer } from "./shopify/reducers";
import { cartUIReducer } from "./cartUI/reducers";
import { variantsReducer } from "./variants/reducers";
import { composeWithDevTools } from "redux-devtools-extension";
import reduxThunk from "redux-thunk";
const rootReducer = combineReducers({
    shopify: shopifyReducer,
    cartUI: cartUIReducer,
    variants: variantsReducer,
});

export type RootState = ReturnType<typeof rootReducer>;

export const store = createStore(
    rootReducer,
    composeWithDevTools(applyMiddleware(reduxThunk))
);