From c72fc6eac576ce043ab706e13030497a0dab3d3a Mon Sep 17 00:00:00 2001 From: Thomas Zemp Date: Mon, 6 Feb 2023 15:28:06 +0100 Subject: [PATCH] fix: custom error handling --- runtime/src/index.ts | 7 ++++- services/plugin/src/PluginContext.tsx | 28 +++++++++++++++++++ services/plugin/src/PluginSender.tsx | 15 +++++++---- services/plugin/src/PluginWrapper.tsx | 39 +++++++++++++++++---------- services/plugin/src/index.ts | 2 ++ 5 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 services/plugin/src/PluginContext.tsx diff --git a/runtime/src/index.ts b/runtime/src/index.ts index 3339b4d4..e0e9dd5d 100644 --- a/runtime/src/index.ts +++ b/runtime/src/index.ts @@ -22,6 +22,11 @@ export { clearSensitiveCaches, } from '@dhis2/app-service-offline' -export { PluginSender, PluginWrapper } from '@dhis2/app-service-plugin' +export { + PluginSender, + PluginWrapper, + usePluginErrorContext, + PluginErrorProvider, +} from '@dhis2/app-service-plugin' export { Provider } from './Provider' diff --git a/services/plugin/src/PluginContext.tsx b/services/plugin/src/PluginContext.tsx new file mode 100644 index 00000000..cefc26c6 --- /dev/null +++ b/services/plugin/src/PluginContext.tsx @@ -0,0 +1,28 @@ +import React, { createContext, Dispatch, useContext, useState } from 'react' + +type PluginErrorContextType = { + onPluginError: any + setOnPluginError: any +} + +const PluginErrorContext = createContext({ + onPluginError: null, + setOnPluginError: null, +}) + +const PluginErrorProvider = ({ children }: { children: React.Component }) => { + const [onPluginError, setOnPluginError] = useState(null) + const providerValue = { + onPluginError, + setOnPluginError, + } + return ( + + {children} + + ) +} + +const usePluginErrorContext = () => useContext(PluginErrorContext) + +export { PluginErrorContext, PluginErrorProvider, usePluginErrorContext } diff --git a/services/plugin/src/PluginSender.tsx b/services/plugin/src/PluginSender.tsx index e0e30a81..4c00429b 100644 --- a/services/plugin/src/PluginSender.tsx +++ b/services/plugin/src/PluginSender.tsx @@ -76,11 +76,16 @@ export const PluginSender = ({ // if iframe has sent initial request, send new props if (communicationReceived && iframeRef.current.contentWindow) { - postRobot.send( - iframeRef.current.contentWindow, - 'updated', - iframeProps - ) + postRobot + .send( + iframeRef.current.contentWindow, + 'updated', + iframeProps + ) + .catch((err) => { + // log postRobot errors, but do not bubble them up + console.error(err) + }) } } }, [propsToPass, communicationReceived, updateMissingProps]) diff --git a/services/plugin/src/PluginWrapper.tsx b/services/plugin/src/PluginWrapper.tsx index 48cdb69d..7de2e087 100644 --- a/services/plugin/src/PluginWrapper.tsx +++ b/services/plugin/src/PluginWrapper.tsx @@ -1,6 +1,7 @@ import postRobot from 'post-robot' import React, { useCallback, useEffect, useState } from 'react' import { PluginErrorBoundary } from './PluginErrorBoundary' +import { usePluginErrorContext } from './PluginContext' export const PluginWrapper = ({ requiredProps, @@ -9,6 +10,7 @@ export const PluginWrapper = ({ requiredProps: [string] children: any }): any => { + const { setOnPluginError } = usePluginErrorContext() const [propsFromParent, setPropsFromParent] = useState() const receivePropsFromParent = useCallback( @@ -35,19 +37,27 @@ export const PluginWrapper = ({ } else { updateMissingProps(null) } + + if (explictlyPassedProps.onError && setOnPluginError) { + setOnPluginError(() => (error: Error) => { + explictlyPassedProps.onError(error) + }) + } }, - [requiredProps] + [requiredProps, setOnPluginError] ) useEffect(() => { - // make first request for props to communicate that iframe is ready - postRobot - .send(window.top, 'getPropsFromParent') - .then(receivePropsFromParent) - .catch((err: Error) => { - console.error(err) - }) - }, [receivePropsFromParent]) + if (setOnPluginError) { + // make first request for props to communicate that iframe is ready + postRobot + .send(window.top, 'getPropsFromParent') + .then(receivePropsFromParent) + .catch((err: Error) => { + console.error(err) + }) + } + }, [receivePropsFromParent, setOnPluginError]) useEffect(() => { // set up listener to listen for subsequent sends from parent window @@ -62,9 +72,10 @@ export const PluginWrapper = ({ return () => listener.cancel() }, [receivePropsFromParent]) - return ( - - {children({ ...propsFromParent })} - - ) + return children({ ...propsFromParent }) + // return ( + // + // {children({ ...propsFromParent })} + // + // ) } diff --git a/services/plugin/src/index.ts b/services/plugin/src/index.ts index 846e5205..2136a003 100644 --- a/services/plugin/src/index.ts +++ b/services/plugin/src/index.ts @@ -1,3 +1,5 @@ export { PluginSender } from './PluginSender' export { PluginWrapper } from './PluginWrapper' + +export * from './PluginContext'