[英]Client-side routing in an embedded shopify app
我正在尝试在嵌入式 shopify 应用程序中使用react-router
启用客户端路由。 我使用了 Shopify 中的这条指南,但我不清楚./Routes
文件中应该包含什么。 我试图在 Stack overflow 或博客上搜索类似的问题,但那里的信息有点过时了。
我的代码:App.jsx:
import {
ApolloClient,
ApolloProvider,
HttpLink,
InMemoryCache,
} from "@apollo/client";
import {
Provider as AppBridgeProvider,
useAppBridge,
} from "@shopify/app-bridge-react";
import { authenticatedFetch } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
import { AppProvider as PolarisProvider } from "@shopify/polaris";
import translations from "@shopify/polaris/locales/en.json";
import "@shopify/polaris/build/esm/styles.css";
import {useMemo} from 'react';
import {useLocation, useNavigate, BrowserRouter, RouterProvider} from 'react-router-dom';
import { HomePage } from "./components/HomePage";
import Routes from './Routes';
function App() {
const navigate = useNavigate();
const location = useLocation();
const history = useMemo(
() => ({replace: (path) => navigate(path, {replace: true})}),
[navigate],
);
console.log(new URLSearchParams(document.location.search).get("host"))
const router = useMemo(
() => ({
location,
history,
}),
[location, history],
);
return (
<PolarisProvider i18n={translations}>
<AppBridgeProvider
config={{
apiKey: process.env.SHOPIFY_API_KEY,
host: new URLSearchParams(document.location.search).get("host"),
forceRedirect: true,
}}
router={router}
>
<MyProvider>
<Routes />
</MyProvider>
</AppBridgeProvider>
</PolarisProvider>
);
}
function MyProvider({ children }) {
const app = useAppBridge();
const client = new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
credentials: "include",
fetch: userLoggedInFetch(app),
}),
});
return <ApolloProvider client={client}>{children}</ApolloProvider>;
}
export 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;
};
}
export default function AppWrapper() {
return (
<BrowserRouter>
<App />
</BrowserRouter>
);
}
./Routes.jsx
import React from 'react';
import {createBrowserRouter} from "react-router-dom";
import { HomePage } from './components/HomePage';
import { Instructions } from './components/Instructions';
export default function Routes() {
const routes = createBrowserRouter([
{
path: "/",
element: <HomePage />,
},
{
path: "/statistics",
element: <HomePage />,
},
{
path: "/integration",
element: <Instructions />,
}
]);
return routes
}
非常感谢任何帮助:-)
我认为文档中的重要说明是:
如果您使用的是 React Router,请确保 Provider 是路由器组件的子组件。
代码:
export function MyApp() { const config = { apiKey: '12345', host: host }; const navigate = useNavigate(); const location = useLocation(); const history = useMemo( () => ({ replace: (path) => navigate(path, { replace: true })}), [navigate], ); const router = useMemo( () => ({ location, history, }), [location, history], ); return ( <Provider config={config} router={router} > <Routes /> </Provider> ); } export default function AppWrapper() { return ( <BrowserRouter> // <-- Router wraps App <App /> </BrowserRouter> ); }
这是因为App
组件必然需要从 ReactTree 的更高层提供给它的路由上下文,因此它可以使用useNavigate
和useLocation
挂钩并将history
object 代理到navigate
function。
此时Routes
组件可以是任意渲染一些路由的React组件,进行匹配渲染。 对于您的情况,您不能使用createBrowserRouter
并在尝试使用它的App
组件下方定义路由器。 在上面的AppWrapper
示例中使用旧的BrowserRouter
, Routes
是一个组件,可以呈现您想要的路由。
例子
import React from 'react';
import { useRoutes } from "react-router-dom";
import { HomePage } from './components/HomePage';
import { Instructions } from './components/Instructions';
export default function Routes() {
const routes = useRoutes([
{ path: "/", element: <HomePage /> },
{ path: "/statistics", element: <HomePage /> },
{ path: "/integration", element: <Instructions /> }.
]);
return routes;
}
...
...
import Routes from './Routes';
function App() {
const navigate = useNavigate();
const location = useLocation();
const history = useMemo(
() => ({replace: (path) => navigate(path, {replace: true})}),
[navigate],
);
const router = useMemo(
() => ({
location,
history,
}),
[location, history],
);
return (
<PolarisProvider i18n={translations}>
<AppBridgeProvider
config={{
apiKey: process.env.SHOPIFY_API_KEY,
host: new URLSearchParams(document.location.search).get("host"),
forceRedirect: true,
}}
router={router}
>
<MyProvider>
<Routes />
</MyProvider>
</AppBridgeProvider>
</PolarisProvider>
);
}
如果您想使用新的react-router-dom@6.4
数据 API,那么以下重构可能适合您。 创建新的数据连接BrowserRouter
但重构路由,使App
呈现为布局路由(即它在Route
上呈现,并且它本身呈现嵌套路由的Outlet
以将其内容呈现到)。
例子:
应用程序
...
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
...
function App() {
const navigate = useNavigate();
const location = useLocation();
const history = useMemo(
() => ({replace: (path) => navigate(path, {replace: true})}),
[navigate],
);
const router = useMemo(
() => ({
location,
history,
}),
[location, history],
);
return (
<PolarisProvider i18n={translations}>
<AppBridgeProvider
config={{
apiKey: process.env.SHOPIFY_API_KEY,
host: new URLSearchParams(document.location.search).get("host"),
forceRedirect: true,
}}
router={router}
>
<MyProvider>
<Outlet />
</MyProvider>
</AppBridgeProvider>
</PolarisProvider>
);
}
export default App;
创建Router
。
import React from 'react';
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import App from './path/to/App';
import { HomePage } from './components/HomePage';
import { Instructions } from './components/Instructions';
const router = createBrowserRouter([
{
path="/",
element={<App />}
children: [
{
index: true,
element: <HomePage />,
},
{
path: "/statistics",
element: <HomePage />,
},
{
path: "/integration",
element: <Instructions />,
}
],
},
]);
export default function Router() {
return <RouterProvider router={router} />;
}
...
现在导入并渲染路由器:
import Router from '..path/to/Router';
...
<Router />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.