From 734dff49b024af745f1af641d15fcba2e1c19610 Mon Sep 17 00:00:00 2001 From: Kai Vandivier Date: Mon, 11 Dec 2023 14:16:46 +0100 Subject: [PATCH] feat: add value-indepent hook for setting online status message --- .../use-online-status-message.test.tsx | 2 +- .../offline/src/lib/online-status-message.tsx | 77 ++++++++++++------- services/offline/src/types.ts | 9 --- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/services/offline/src/lib/__tests__/use-online-status-message.test.tsx b/services/offline/src/lib/__tests__/use-online-status-message.test.tsx index fe3d3ddac..e8e37f926 100644 --- a/services/offline/src/lib/__tests__/use-online-status-message.test.tsx +++ b/services/offline/src/lib/__tests__/use-online-status-message.test.tsx @@ -16,7 +16,7 @@ describe('useOnlineStatusMessage', () => { wrapper, }) - expect(result.current.onlineStatusMessage).toBeUndefined() + expect(result.current.onlineStatusMessage).toBeNull() act(() => { result.current.setOnlineStatusMessage('8 offline events') diff --git a/services/offline/src/lib/online-status-message.tsx b/services/offline/src/lib/online-status-message.tsx index 478d668b3..d9f690d2f 100644 --- a/services/offline/src/lib/online-status-message.tsx +++ b/services/offline/src/lib/online-status-message.tsx @@ -1,39 +1,64 @@ import React, { ReactElement, ReactNode, useContext, useState } from 'react' -import { OnlineStatusMessageContextAPI } from '../types' -const defaultApi: OnlineStatusMessageContextAPI = { - onlineStatusMessage: undefined, - setOnlineStatusMessage: () => undefined, -} - -const OnlineStatusMessageContext = - React.createContext(defaultApi) +type SetOnlineStatusMessage = (message: ReactNode) => void -export const useOnlineStatusMessage = (): OnlineStatusMessageContextAPI => { - const { onlineStatusMessage, setOnlineStatusMessage } = - useContext(OnlineStatusMessageContext) - - return { - onlineStatusMessage, - setOnlineStatusMessage, - } -} +// 'get' and 'set' contexts are separated so 'setter' consumers that don't +// actually need the value don't have to rerender when the value changes: +const OnlineStatusMessageValueContext = React.createContext(null) +const SetOnlineStatusMessageContext = + React.createContext(() => undefined) export const OnlineStatusMessageProvider = ({ children, }: { children: ReactNode }): ReactElement => { - const [onlineStatusMessage, setOnlineStatusMessage] = useState() + const [onlineStatusMessage, setOnlineStatusMessage] = + useState(null) // note: not undefined return ( - - {children} - + + + {children} + + ) } + +export const useOnlineStatusMessageValue = () => { + const onlineStatusMessage = useContext(OnlineStatusMessageValueContext) + + // note: value is initialized to `null` in provider, not undefined + if (onlineStatusMessage === undefined) { + throw new Error( + 'useOnlineStatusMessageValue must be used within an OnlineStatusMessageProvider' + ) + } + + return onlineStatusMessage +} + +export const useSetOnlineStatusMessage = () => { + const setOnlineStatusMessage = useContext(SetOnlineStatusMessageContext) + + if (setOnlineStatusMessage === undefined) { + throw new Error( + 'useSetOnlineStatusMessage must be used within an OnlineStatusMessageProvider' + ) + } + + return setOnlineStatusMessage +} + +// combination of both getter and setter (also provides backward compatability) +export const useOnlineStatusMessage = () => { + const onlineStatusMessage = useOnlineStatusMessageValue() + const setOnlineStatusMessage = useSetOnlineStatusMessage() + + return { + onlineStatusMessage, + setOnlineStatusMessage, + } +} diff --git a/services/offline/src/types.ts b/services/offline/src/types.ts index 730d9f13c..37580b406 100644 --- a/services/offline/src/types.ts +++ b/services/offline/src/types.ts @@ -1,5 +1,3 @@ -import { ReactNode } from 'react' - // Cacheable Section types export type RecordingState = 'default' | 'pending' | 'error' | 'recording' @@ -66,10 +64,3 @@ export interface OfflineInterface { getCachedSections: () => Promise removeSection: (id: string) => Promise } - -// Online status types - -export type OnlineStatusMessageContextAPI = { - onlineStatusMessage?: ReactNode - setOnlineStatusMessage: (additionalInfo: ReactNode) => void -}