The Client Runtime provides browser-side functionality for hydration, navigation, and React Server Components client integration in RedwoodSDK applications.
Initializes the React client and hydrates the RSC payload from the server.
/**
* Initializes the React client and hydrates the application
* @param options - Configuration options for client initialization
*/
function initClient(options?: {
/** Custom transport for RSC communication (defaults to fetchTransport) */
transport?: Transport;
/** React hydration options */
hydrateRootOptions?: HydrationOptions;
/** Custom response handler for navigation */
handleResponse?: (response: Response) => boolean;
}): void;
type Transport = (
context: TransportContext
) => Promise<ReadableStream<Uint8Array>>;
interface TransportContext {
request: Request;
serverAction?: {
id: string;
args: any[];
};
}
interface HydrationOptions {
onRecoverableError?: (error: Error) => void;
}Usage Example:
// client.tsx
import { initClient } from 'rwsdk/client';
// Basic initialization
initClient();
// With custom options
initClient({
hydrateRootOptions: {
onRecoverableError: (error) => {
console.error('Hydration error:', error);
},
},
});Initializes client-side navigation with custom behavior and scroll management.
/**
* Initializes client-side navigation
* @param opts - Navigation configuration options
* @returns Object with handleResponse function for custom response handling
*/
function initClientNavigation(opts?: ClientNavigationOptions): {
handleResponse: (response: Response) => boolean;
};
interface ClientNavigationOptions {
/** Callback invoked on each navigation */
onNavigate?: () => void;
/** Whether to scroll to top on navigation (default: true) */
scrollToTop?: boolean;
/** Scroll behavior (default: "auto") */
scrollBehavior?: "auto" | "smooth" | "instant";
}Usage Example:
import { initClient, initClientNavigation } from 'rwsdk/client';
// Initialize with navigation
const { handleResponse } = initClientNavigation({
scrollToTop: true,
scrollBehavior: 'smooth',
onNavigate: () => {
console.log('Navigation occurred');
},
});
initClient({ handleResponse });Navigates to a different route programmatically from client-side code.
/**
* Programmatically navigate to a new route
* @param href - Target URL (can be relative or absolute)
* @param options - Navigation options
*/
function navigate(
href: string,
options?: NavigateOptions
): void;
interface NavigateOptions {
/** History manipulation method (default: "push") */
history?: "push" | "replace";
/** Additional navigation info */
info?: {
/** Override scrollToTop for this navigation */
scrollToTop?: boolean;
/** Override scrollBehavior for this navigation */
scrollBehavior?: string;
};
}Usage Example:
import { navigate } from 'rwsdk/client';
// Simple navigation
navigate('/dashboard');
// Replace history instead of push
navigate('/login', { history: 'replace' });
// Custom scroll behavior
navigate('/profile', {
info: {
scrollToTop: false,
},
});Validates click events for navigation interception.
/**
* Validates whether a click event should trigger client-side navigation
* @param event - Mouse event from click
* @param target - Target anchor element
* @returns True if event should trigger navigation
*/
function validateClickEvent(
event: MouseEvent,
target: HTMLAnchorElement
): boolean;Transport layer for RSC communication between client and server.
/**
* Default fetch-based transport for RSC
*/
const fetchTransport: Transport;
/**
* Creates a reference to a server function callable from client
* @param id - Server function module ID
* @param name - Server function name
* @returns Callable function that communicates with server
*/
function createServerReference(id: string, name: string): Function;Consumes server-sent event streams for realtime updates.
/**
* Consumes server-sent event streams
* @param options - Configuration with chunk handler
*/
function consumeEventStream(options: {
onChunk: (chunk: string) => void;
}): void;Component wrapper that only renders its children on the client-side.
/**
* Renders children only on client-side (not during SSR)
*/
const ClientOnly: React.ComponentType<{ children: React.ReactNode }>;Usage Example:
import { ClientOnly } from 'rwsdk/client';
function MyComponent() {
return (
<ClientOnly>
<BrowserOnlyWidget />
</ClientOnly>
);
}RedwoodSDK re-exports React for convenience.
const React: typeof import('react');
type Dispatch<A> = import('react').Dispatch<A>;
type MutableRefObject<T> = import('react').MutableRefObject<T>;
type SetStateAction<S> = import('react').SetStateAction<S>;interface ActionResponse<Result> {
result?: Result;
error?: Error;
}The typical client initialization pattern combines navigation and client initialization:
// client.tsx
import { initClient, initClientNavigation } from 'rwsdk/client';
const { handleResponse } = initClientNavigation({
scrollToTop: true,
scrollBehavior: 'smooth',
});
initClient({
handleResponse,
hydrateRootOptions: {
onRecoverableError: (error) => {
console.error('Hydration error:', error);
},
},
});