Fix iframe reloaded on each theme change (#3491)
* Fix iframe reloaded on each theme change * CR
This commit is contained in:
parent
7a3d311aaf
commit
593867f0c5
2 changed files with 62 additions and 20 deletions
|
@ -1,15 +1,14 @@
|
||||||
import { useAppDashboardUpdates } from "@dashboard/apps/components/AppFrame/useAppDashboardUpdates";
|
import { useAppDashboardUpdates } from "@dashboard/apps/components/AppFrame/useAppDashboardUpdates";
|
||||||
import {
|
import {
|
||||||
AppDetailsUrlQueryParams,
|
AppDetailsUrlQueryParams,
|
||||||
AppUrls,
|
|
||||||
prepareFeatureFlagsList,
|
prepareFeatureFlagsList,
|
||||||
} from "@dashboard/apps/urls";
|
} from "@dashboard/apps/urls";
|
||||||
import { useAllFlags } from "@dashboard/hooks/useFlags";
|
import { useAllFlags } from "@dashboard/hooks/useFlags";
|
||||||
import { CircularProgress } from "@material-ui/core";
|
import { CircularProgress } from "@material-ui/core";
|
||||||
import { useTheme } from "@saleor/macaw-ui";
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import React from "react";
|
import React, { useCallback, useMemo } from "react";
|
||||||
|
|
||||||
|
import { AppIFrame } from "./AppIFrame";
|
||||||
import { useStyles } from "./styles";
|
import { useStyles } from "./styles";
|
||||||
import { useAppActions } from "./useAppActions";
|
import { useAppActions } from "./useAppActions";
|
||||||
import useTokenRefresh from "./useTokenRefresh";
|
import useTokenRefresh from "./useTokenRefresh";
|
||||||
|
@ -21,7 +20,6 @@ interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
params?: AppDetailsUrlQueryParams;
|
params?: AppDetailsUrlQueryParams;
|
||||||
refetch?: () => void;
|
refetch?: () => void;
|
||||||
onLoad?(): void;
|
|
||||||
onError?(): void;
|
onError?(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,13 +30,11 @@ export const AppFrame: React.FC<Props> = ({
|
||||||
appToken,
|
appToken,
|
||||||
appId,
|
appId,
|
||||||
className,
|
className,
|
||||||
params = {},
|
params,
|
||||||
onLoad,
|
|
||||||
onError,
|
onError,
|
||||||
refetch,
|
refetch,
|
||||||
}) => {
|
}) => {
|
||||||
const frameRef = React.useRef<HTMLIFrameElement | null>(null);
|
const frameRef = React.useRef<HTMLIFrameElement | null>(null);
|
||||||
const { themeType } = useTheme();
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const appOrigin = getOrigin(src);
|
const appOrigin = getOrigin(src);
|
||||||
const flags = useAllFlags();
|
const flags = useAllFlags();
|
||||||
|
@ -60,7 +56,7 @@ export const AppFrame: React.FC<Props> = ({
|
||||||
|
|
||||||
useTokenRefresh(appToken, refetch);
|
useTokenRefresh(appToken, refetch);
|
||||||
|
|
||||||
const handleLoad = () => {
|
const handleLoad = useCallback(() => {
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*
|
*
|
||||||
|
@ -76,11 +72,9 @@ export const AppFrame: React.FC<Props> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
setHandshakeDone(true);
|
setHandshakeDone(true);
|
||||||
|
}, [appToken, postToExtension, setHandshakeDone]);
|
||||||
|
|
||||||
if (onLoad) {
|
const featureFlags = useMemo(() => prepareFeatureFlagsList(flags), [flags]);
|
||||||
onLoad();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -89,19 +83,17 @@ export const AppFrame: React.FC<Props> = ({
|
||||||
<CircularProgress color="primary" />
|
<CircularProgress color="primary" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<iframe
|
<AppIFrame
|
||||||
ref={frameRef}
|
ref={frameRef}
|
||||||
src={AppUrls.resolveAppIframeUrl(appId, src, {
|
src={src}
|
||||||
...params,
|
appId={appId}
|
||||||
featureFlags: prepareFeatureFlagsList(flags),
|
featureFlags={featureFlags}
|
||||||
theme: themeType,
|
params={params}
|
||||||
})}
|
|
||||||
onError={onError}
|
|
||||||
onLoad={handleLoad}
|
onLoad={handleLoad}
|
||||||
|
onError={onError}
|
||||||
className={clsx(classes.iframe, className, {
|
className={clsx(classes.iframe, className, {
|
||||||
[classes.iframeHidden]: !handshakeDone,
|
[classes.iframeHidden]: !handshakeDone,
|
||||||
})}
|
})}
|
||||||
sandbox="allow-same-origin allow-forms allow-scripts"
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
50
src/apps/components/AppFrame/AppIFrame.tsx
Normal file
50
src/apps/components/AppFrame/AppIFrame.tsx
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import { AppDetailsUrlQueryParams, AppUrls } from "@dashboard/apps/urls";
|
||||||
|
import { ThemeType } from "@saleor/app-sdk/app-bridge";
|
||||||
|
import { useTheme } from "@saleor/macaw-ui";
|
||||||
|
import isEqualWith from "lodash/isEqualWith";
|
||||||
|
import React, { forwardRef, memo, useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
interface AppIFrameProps {
|
||||||
|
appId: string;
|
||||||
|
src: string;
|
||||||
|
featureFlags: Record<string, string>;
|
||||||
|
params: AppDetailsUrlQueryParams;
|
||||||
|
onLoad: () => void;
|
||||||
|
onError: () => void;
|
||||||
|
className: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _AppIFrame = forwardRef<HTMLIFrameElement, AppIFrameProps>(
|
||||||
|
({ appId, src, featureFlags, params, onLoad, onError, className }, ref) => {
|
||||||
|
const themeRef = useRef<ThemeType>();
|
||||||
|
const { themeType } = useTheme();
|
||||||
|
|
||||||
|
// Ignore updates to themeType - iframe will be notified via events
|
||||||
|
// Otherwise this will cause reload of entire iframe
|
||||||
|
useEffect(() => {
|
||||||
|
themeRef.current = themeType;
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const iframeSrc = AppUrls.resolveAppIframeUrl(appId, src, {
|
||||||
|
...params,
|
||||||
|
featureFlags,
|
||||||
|
theme: themeRef.current,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<iframe
|
||||||
|
ref={ref}
|
||||||
|
src={iframeSrc}
|
||||||
|
onLoad={onLoad}
|
||||||
|
onError={onError}
|
||||||
|
className={className}
|
||||||
|
sandbox="allow-same-origin allow-forms allow-scripts"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const AppIFrame = memo(_AppIFrame, (prev, next) =>
|
||||||
|
isEqualWith(prev, next),
|
||||||
|
);
|
Loading…
Reference in a new issue