How to use app bridge with my own redux store ?

Solved
barisozdogan
New Member
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,

0 Likes
Trish_Ta
Shopify Staff
Shopify Staff
56 13 21

This is an accepted solution.

Hi  

Hope this helps!


Trish

0 Likes
mattfrancis888
New Member
3 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))
);

 

 

0 Likes