Встроенное приложение Shopify - загрузка разных страниц не работает с использованием nextjs

У меня есть следующая настройка: при загрузке новой страницы с помощью маршрутизатора nextjs она не работает, так как новая страница пуста. Кажется, что перенаправление навигации на стороне клиента или iframe вообще не происходит.

Я успешно использовал Polaris Linkкомпоненты для перехода со страницы на страницу, но это, похоже, полностью перезагружает мое приложение. Я хотел бы использовать маршрутизацию на стороне клиента и даже безуспешно следовал этому примеру /questions/54896155/stranitsyi-perezagruzhayutsya-vmesto-perenapravleniya-v-prilozhenii-shopify-next/54896167#54896167

_app.js

      import {
  ApolloClient,
  ApolloProvider,
  ApolloLink,
  HttpLink,
  InMemoryCache,
} from "@apollo/client";
import App from "next/app";
import { AppProvider } from "@shopify/polaris";
import { Provider, useAppBridge } from "@shopify/app-bridge-react";
import { authenticatedFetch } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
import "@shopify/polaris/build/esm/styles.css";
import translations from "@shopify/polaris/locales/en.json";
import RoutePropagator from "../components/RoutePropagator";
import { useAppRoute } from "src/hooks/useAppRoute";
import { ShopifySettingsProvider } from "src/contexts/ShopifySettings";

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

  return async (uri, options) => {
    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;
  };
}

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

  const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: ApolloLink.split(
      (operation) => operation.getContext().clientName === "shopify",
      new HttpLink({
        uri: "/graphql-shopify",
        fetch: userLoggedInFetch(app),
        fetchOptions: {
          credentials: "include",
        },
      }),
      new HttpLink({ uri: "/graphql" })
    ),
  });

  const { shop } = props;

  return (
    <ApolloProvider client={client}>
      <ShopifySettingsProvider shop={shop}>
        {props.children}
      </ShopifySettingsProvider>
    </ApolloProvider>
  );
}

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

MyApp.getInitialProps = async ({ ctx }) => {
  console.log(ctx);
  return {
    host: ctx.query.host,
  };
};

export default MyApp;

RoutePropigator.js

      import React, {useEffect, useContext} from 'react';
import Router, { useRouter } from "next/router";
import { Context as AppBridgeContext } from "@shopify/app-bridge-react";
import { Redirect } from "@shopify/app-bridge/actions";
import { RoutePropagator as ShopifyRoutePropagator } from "@shopify/app-bridge-react";

const RoutePropagator = () => {
  const router = useRouter();
  const { asPath } = router;
  const appBridge = React.useContext(AppBridgeContext);

  // Subscribe to appBridge changes - captures appBridge urls
  // and sends them to Next.js router. Use useEffect hook to
  // load once when component mounted
  useEffect(() => {
    appBridge.subscribe(Redirect.Action.APP, ({ path }) => {
      Router.push(path);
    });
  }, []);

  return appBridge && asPath ? (
    <ShopifyRoutePropagator location={asPath} app={appBridge} />
  ) : null;
}

export default RoutePropagator;

index.js — пример router.push

      import React, { useState } from "react";
import Link from "next/link";
import {
  Frame,
  Page,
  Layout,
  EmptyState,
  Button,
  Card,
} from "@shopify/polaris";
import { ResourcePicker, TitleBar } from "@shopify/app-bridge-react";
import store from "store-js";
import ResourceListWithProducts from "../components/elements/ResourceList";
import Sidebar from "../components/Sidebar";
import { useRouter } from 'next/router'

const img = "https://cdn.shopify.com/s/files/1/0757/9955/files/empty-state.svg";

const Index = () => {
  const router = useRouter()
  const [open, setOpen] = useState(false);

  // A constant that defines your app's empty state
  const emptyState = !store.get("ids");
  const handleSelection = (resources) => {
    const idsFromResources = resources.selection.map((product) => product.id);
    setOpen(false);
    store.set("ids", idsFromResources);
  };

  return (
    <Frame navigation={<Sidebar />}>
      <Page>
        <TitleBar />
        <ResourcePicker
          resourceType="Product"
          showVariants={false}
          open={open}
          onSelection={(resources) => handleSelection(resources)}
          onCancel={() => setOpen(false)}
        />
        {emptyState ? ( // Controls the layout of your app's empty state
          <Layout>
            <EmptyState heading="Customise your product" image={img}>
              <p>Add options to customise your product.<button onClick={() => router.push('/colours')}>Go to colours</button></p>
            </EmptyState>
          </Layout>
        ) : (
          // Uses the new resource list that retrieves products by IDs
          <ResourceListWithProducts />
        )}
      </Page>
    </Frame>
  );
};

export default Index;

2 ответа

Итак, решение для решения этой проблемы было первым, чтобы в основном реализовать _app.js, RoutePropigaterпример кода выложен здесь https://github.com/carstenlebek/shopify-node-app-starter

Также, в частности, мне пришлось также обновить пакеты узлов до тех же версий, что и в этом примере стартового пакета. Надеюсь, это поможет другим людям

Я пробовал аналогичный подход с RoutePropagatorно подписка на самом деле не срабатывает надежно при изменении страницы.

Я просто не думаю, что Shopify будет поддерживать NextJS, особенно с изменением инструмента CLI, который теперь формирует пользовательскую сборку вместо использования NextJS + Koa.

Другие вопросы по тегам