我有以下设置,当使用nextjs路由器加载新页时,由于新页为空,它无法工作。似乎根本没有客户端或基于iframe的导航重定向发生。
我已经成功地使用北极星Link组件从一个页面导航到另一个页面,但这似乎完全重新加载了我的应用程序在iframe。我想使用客户端路由,甚至在没有运气的情况下都遵循了这个示例https://stackoverflow.com/a/63481122/671095。
我正在使用名为useAppRoute的自定义钩子来连接shopify-app-bridge的历史,但我不认为这是我想要实现的最好的方法。
_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>
);
}
function PolarisLink({ url, children, external, ...rest }) {
if (external) {
return (
<a href={url} {...rest}>
{children}
</a>
);
}
const redirect = useAppRoute();
return (
<span
onClick={(e) => {
console.log("redirected");
e.preventDefault();
e.stopPropagation();
redirect(url);
}}
>
<a {...rest}>{children}</a>
</span>
);
}
class MyApp extends App {
render() {
const { Component, pageProps, host, shop } = this.props;
console.log(host);
console.log(shop);
return (
<AppProvider i18n={translations} linkComponent={PolarisLink}>
<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;useAppRoute.js
import { useRouter } from "next/router";
import { useAppBridge } from "@shopify/app-bridge-react";
import { History } from "@shopify/app-bridge/actions";
export function useAppRoute() {
const app = useAppBridge();
const router = useRouter();
const history = History.create(app);
return (path) => {
const [, asPath] = router.asPath.split("?");
const pagePath = path.replace(/\/\d+/g, "/[id]");
router.push(pagePath, `${path}?${asPath}`).then(() => {
history.dispatch(History.Action.REPLACE, path);
});
};
}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;发布于 2022-01-18 05:41:06
因此,解决这一问题的解决方案首先基本实现了_app.js,RoutePropigater代码示例,这里列出了https://github.com/carstenlebek/shopify-node-app-starter。
另外,我还必须将我的节点包更新为与这个初学者包示例相同的版本。希望这对其他人有帮助
发布于 2022-01-18 01:40:21
我在RoutePropagator上尝试过类似的方法,但是订阅实际上并不能可靠地启动页面更改。
我只是不认为Shopify将支持NextJS -特别是随着CLI工具的改变,现在脚手架是一个定制的构建,而不是使用NextJS + Koa。
https://stackoverflow.com/questions/70697595
复制相似问题