11import { useEffect , useState } from "react" ;
22
3+ /** Expected structure of the postMessage data from parent window */
4+ interface RenderDataMessage {
5+ type : string ;
6+ payload ?: {
7+ renderData ?: unknown ;
8+ } ;
9+ }
10+
11+ /** Return type for the useRenderData hook */
12+ interface UseRenderDataResult < T > {
13+ data : T | null ;
14+ isLoading : boolean ;
15+ error : string | null ;
16+ }
17+
318/**
419 * Hook for receiving render data from parent window via postMessage
520 * This is used by iframe-based UI components that receive data from an MCP client
@@ -22,13 +37,13 @@ import { useEffect, useState } from "react";
2237 * }
2338 * ```
2439 */
25- export function useRenderData < T = unknown > ( ) {
40+ export function useRenderData < T = unknown > ( ) : UseRenderDataResult < T > {
2641 const [ data , setData ] = useState < T | null > ( null ) ;
2742 const [ isLoading , setIsLoading ] = useState ( true ) ;
2843 const [ error , setError ] = useState < string | null > ( null ) ;
2944
3045 useEffect ( ( ) => {
31- const handleMessage = ( event : MessageEvent ) => {
46+ const handleMessage = ( event : MessageEvent < RenderDataMessage > ) : void => {
3247 if ( event . data ?. type !== "ui-lifecycle-iframe-render-data" ) {
3348 // Silently ignore messages that aren't for us
3449 return ;
@@ -64,7 +79,7 @@ export function useRenderData<T = unknown>() {
6479 window . addEventListener ( "message" , handleMessage ) ;
6580 window . parent . postMessage ( { type : "ui-lifecycle-iframe-ready" } , "*" ) ;
6681
67- return ( ) => {
82+ return ( ) : void => {
6883 window . removeEventListener ( "message" , handleMessage ) ;
6984 } ;
7085 } , [ ] ) ;
0 commit comments