1- import { createContext , useContext , useEffect , useState , useCallback } from "react" ;
1+ import { createContext , useContext , useEffect , useState , useCallback , useRef } from "react" ;
22import { createClient } from "@/common/orpc/client" ;
33import { RPCLink as WebSocketLink } from "@orpc/client/websocket" ;
44import { RPCLink as MessagePortLink } from "@orpc/client/message-port" ;
@@ -86,11 +86,15 @@ export const ORPCProvider = (props: ORPCProviderProps) => {
8686 return urlParams . get ( "token" ) ?? getStoredAuthToken ( ) ;
8787 } ) ;
8888
89+ // Track cleanup function in a ref to avoid stale closure in useEffect cleanup
90+ const cleanupRef = useRef < ( ( ) => void ) | null > ( null ) ;
91+
8992 const connect = useCallback (
9093 ( token : string | null ) => {
9194 // If client provided externally, use it directly
9295 if ( props . client ) {
9396 window . __ORPC_CLIENT__ = props . client ;
97+ cleanupRef . current = null ; // External client - no cleanup needed
9498 setState ( { status : "connected" , client : props . client , cleanup : ( ) => undefined } ) ;
9599 return ;
96100 }
@@ -99,6 +103,7 @@ export const ORPCProvider = (props: ORPCProviderProps) => {
99103 if ( window . api ) {
100104 const { client, cleanup } = createElectronClient ( ) ;
101105 window . __ORPC_CLIENT__ = client ;
106+ cleanupRef . current = cleanup ;
102107 setState ( { status : "connected" , client, cleanup } ) ;
103108 return ;
104109 }
@@ -113,6 +118,7 @@ export const ORPCProvider = (props: ORPCProviderProps) => {
113118 . ping ( "auth-check" )
114119 . then ( ( ) => {
115120 window . __ORPC_CLIENT__ = client ;
121+ cleanupRef . current = cleanup ;
116122 setState ( { status : "connected" , client, cleanup } ) ;
117123 } )
118124 . catch ( ( err : unknown ) => {
@@ -166,9 +172,9 @@ export const ORPCProvider = (props: ORPCProviderProps) => {
166172 connect ( authToken ) ;
167173
168174 return ( ) => {
169- if ( state . status === "connected" ) {
170- state . cleanup ( ) ;
171- }
175+ // Use ref to get current cleanup function - avoids stale closure issue
176+ // where state captured at mount time would always be "connecting"
177+ cleanupRef . current ?. ( ) ;
172178 } ;
173179 // Only run on mount and when authToken changes via handleAuthSubmit
174180 // eslint-disable-next-line react-hooks/exhaustive-deps
0 commit comments