User Strike72 on discord encountered an issue where his react client doesn't correctly trigger their ClientDisconnected reducer: https://discord.com/channels/1037340874172014652/1424993383302041612
I guessed that this user was using the new react-hooks and took a look at the SpacetimeDBProvider. 🕵️
Right now the SpacetimeDBProvider builds the connection immediately, but never tears it down, so when the user refreshes or navigates away, the websocket stays open until it dies from inactivity or the browser closes. This leads to users not properly disconnecting from SpacetimeDB and frustration.
To clean up properly, the connection should be built inside a useEffect inside the provider itself, and call disconnect() in the cleanup function. Here is a drop-in replacement of the SpacetimeDBProvider.ts file that does exactly this:
import React from 'react';
import {
DbConnectionBuilder,
type DbConnectionImpl,
} from '../sdk/db_connection_impl';
import { SpacetimeDBContext } from './useSpacetimeDB';
export interface SpacetimeDBProviderProps<
DbConnection extends DbConnectionImpl,
ErrorContext,
SubscriptionEventContext,
> {
connectionBuilder: DbConnectionBuilder<
DbConnection,
ErrorContext,
SubscriptionEventContext
>;
children?: React.ReactNode;
}
export function SpacetimeDBProvider<
DbConnection extends DbConnectionImpl,
ErrorContext,
SubscriptionEventContext,
>({
connectionBuilder,
children,
}: SpacetimeDBProviderProps<
DbConnection,
ErrorContext,
SubscriptionEventContext
>): React.JSX.Element {
const [connection, setConnection] = React.useState<DbConnection | null>(null);
React.useEffect(() => {
const conn = connectionBuilder.build();
setConnection(conn);
return () => {
try {
conn.disconnect();
} catch (err) {
console.warn('[SpacetimeDBProvider] Error during disconnect:', err);
}
};
}, [connectionBuilder]);
if (!connection) return React.createElement(React.Fragment, null);
return React.createElement(
SpacetimeDBContext.Provider,
{ value: connection },
children
);
}
We're building the connection lazily inside the useEffect, and we're .disconnect()ing on unmount to automatically clean up the websocket. While the connection is initializing, we're also dropping in a placeholder React.Fragment.
I've confirmed this fix in my react-hooks test repo, although the above change won't be included since it's a modification of the npm package.
User
Strike72on discord encountered an issue where his react client doesn't correctly trigger theirClientDisconnectedreducer: https://discord.com/channels/1037340874172014652/1424993383302041612I guessed that this user was using the new react-hooks and took a look at the
SpacetimeDBProvider. 🕵️Right now the
SpacetimeDBProviderbuilds the connection immediately, but never tears it down, so when the user refreshes or navigates away, the websocket stays open until it dies from inactivity or the browser closes. This leads to users not properly disconnecting from SpacetimeDB and frustration.To clean up properly, the connection should be built inside a
useEffectinside the provider itself, and calldisconnect()in the cleanup function. Here is a drop-in replacement of theSpacetimeDBProvider.tsfile that does exactly this:We're building the connection lazily inside the
useEffect, and we're.disconnect()ing on unmount to automatically clean up the websocket. While the connection is initializing, we're also dropping in a placeholderReact.Fragment.I've confirmed this fix in my react-hooks test repo, although the above change won't be included since it's a modification of the npm package.