-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #265 from belk1ng/feat/usePostMessage
feat: add usePostMessage hook
- Loading branch information
Showing
3 changed files
with
96 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { usePostMessage } from './usePostMessage'; | ||
|
||
const Demo = () => { | ||
const { postMessage } = usePostMessage<string>((event) => { | ||
if (location.origin === event.origin) { | ||
console.log('MessageEvent: ', event); | ||
} | ||
}); | ||
|
||
const onClick = () => { | ||
postMessage(window, 'Custom Message', { | ||
targetOrigin: '*' | ||
}); | ||
}; | ||
|
||
return ( | ||
<section> | ||
<button onClick={onClick}>Click to post message</button> | ||
</section> | ||
); | ||
}; | ||
|
||
export default Demo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { useEffect } from 'react'; | ||
|
||
/** The possible entity types */ | ||
type PossibleEntity = Window | Worker | MessagePort; | ||
|
||
/** The use post message entity arguments */ | ||
type PostMessageEntityArguments<Entity extends PossibleEntity> = Entity['postMessage'] extends ( | ||
message: unknown, | ||
...rest: infer Rest | ||
) => void | ||
? Rest | ||
: never; | ||
|
||
/** The use post message return type */ | ||
export interface UsePostMessageReturn<MessagePayload> { | ||
postMessage: <Entity extends PossibleEntity>( | ||
targetSource: Entity, | ||
message: MessagePayload, | ||
...args: PostMessageEntityArguments<Entity> | ||
) => void; | ||
} | ||
|
||
/** | ||
* @name usePostMessage | ||
* @description - Hook that allows you to use `postMessage` function | ||
* @category Browser | ||
* | ||
* @overload | ||
* @template MessagePayload The message data type | ||
* @param {(message: MessageEvent<MessagePayload>) => void} onMessage callback to get received message event | ||
* @returns {UsePostMessageReturn} An object with a patched `postMethod` function | ||
* | ||
* @example | ||
* const { postMessage } = usePostMessage(); | ||
*/ | ||
export const usePostMessage = <MessagePayload = unknown>( | ||
onMessage?: (message: MessageEvent<MessagePayload>) => void | ||
): UsePostMessageReturn<MessagePayload> => { | ||
const postMessage = <Entity extends PossibleEntity>( | ||
targetSource: Entity, | ||
message: MessagePayload, | ||
...args: unknown[] | ||
) => { | ||
if (targetSource instanceof Window) { | ||
targetSource.postMessage(message, ...(args as PostMessageEntityArguments<Window>)); | ||
} else if (targetSource instanceof Worker) { | ||
targetSource.postMessage(message, ...(args as PostMessageEntityArguments<Worker>)); | ||
} else { | ||
targetSource.postMessage(message, ...(args as PostMessageEntityArguments<MessagePort>)); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
const controller = new AbortController(); | ||
|
||
window.addEventListener( | ||
'message', | ||
(event: MessageEvent<MessagePayload>) => { | ||
onMessage?.(event); | ||
}, | ||
{ signal: controller.signal } | ||
); | ||
|
||
return () => { | ||
controller.abort(); | ||
}; | ||
}, [onMessage]); | ||
|
||
return { | ||
postMessage | ||
}; | ||
}; |