Suspensive Documentation
website·Indexed 32 days ago
https://suspensive.orgA library providing async-safe React primitives and components. It includes @suspensive/react, which offers drop-in replacements and enhancements for React.Suspense and ErrorBoundary, as well as utilities like ClientOnly, DefaultPropsProvider, and the useIsClient hook. The documentation also covers @suspensive/react-query and its migration path to TanStack Query v4.
What's inside Suspensive
- Suspensive is a library designed to fill gaps in React's built-in async rendering, error handling, and data fetching capabilities. It provides declarative components and hooks to simplify the implementation of Suspense boundaries, Error Boundaries, and lazy loading, while also offering specialized integrations for TanStack Query and Jotai to reduce boilerplate and improve SSR (Server-Side Rendering) behavior.
Handle removed options in useSuspenseQuery and useSuspenseInfiniteQuery
In recent versions, theenabledandplaceholderDataoptions have been removed fromuseSuspenseQueryanduseSuspenseInfiniteQuery. These options are incompatible with the Suspense architecture.const query = useSuspenseQuery({ queryKey: ['key'], queryFn: () => api.text() - enabled: Math.random() > 0.5, - placeholderData: 'placeholder' })Use @suspensive/react Suspense as a replacement for React.Suspense
@suspensive/react's<Suspense/>is a drop-in replacement for React's native<Suspense>component. It maintains the same basic suspense boundary functionality but adds support for skipping server-side rendering (SSR), global default fallbacks viaDefaultPropsProvider, and a Higher-Order Component (HOC) pattern viaSuspense.with.import { Suspense } from '@suspensive/react' const Example = () => ( <Suspense fallback={<Loading />}> <Children /> </Suspense> )Migrate from react-error-boundary to @suspensive/react
Migrating fromreact-error-boundaryinvolves updating the fallback prop name and the reset function name.fallbackRenderorFallbackComponentbecomesfallback, andresetErrorBoundarybecomesreset.// From react-error-boundary <ErrorBoundary fallbackRender={({ error, resetErrorBoundary }) => <div onClick={resetErrorBoundary}>{error.message}</div>} onReset={() => console.log('reset')} > <YourComponent /> </ErrorBoundary> // To @suspensive/react <ErrorBoundary fallback={({ error, reset }) => <div onClick={reset}>{error.message}</div>} onReset={() => console.log('reset')} > <YourComponent /> </ErrorBoundary>Prevent loading state flicker with the Delay component
The
<Delay/>component prevents 'flash-of-loading-state' by holding back the loading UI until a specified time (ms) has passed. This is particularly useful when used as a fallback for<Suspense/>to hide spinners on fast networks.Recommended
msvalues:- 100–300ms: Standard UI to hide spinners on fast networks.
- 500ms+: Non-critical sections where delayed feedback is acceptable.
<Suspense fallback={ <Delay ms={200}> {({ isDelayed }) => ( <Spinner style={{ opacity: isDelayed ? 1 : 0, transition: 'opacity 200ms' }} /> )} </Delay> } > <Content /> </Suspense>Use queryOptions for reusable query configurations
ThequeryOptionspattern allows you to define query configurations (likequeryKeyandqueryFn) in a reusable way. These options can be passed directly into various hooks (useQuery,useSuspenseQuery,useQueries,useSuspenseQueries) and the<SuspenseQuery />component, as well asqueryClientmethods.// Define reusable options const postQueryOptions = (id: number) => queryOptions({ queryKey: ['posts', id], queryFn: () => fetchPost(id), }); // Use in hooks const { data: post1 } = useSuspenseQuery({ ...postQueryOptions(1), refetchInterval: 2000, }); // Use in components const Example = () => ( <SuspenseQuery {...postQueryOptions(1)}> {({ data: post1 }) => <>{post1.text}</>} </SuspenseQuery> ); // Use with QueryClient const queryClient = useQueryClient(); queryClient.prefetchQuery(postQueryOptions(1)); queryClient.invalidateQueries(postQueryOptions(1));Prefetch and hydrate multiple queries in Server Components using QueriesHydration
The
<QueriesHydration />component simplifies the process of prefetching data on the server and hydrating it on the client in React Server Components (RSC) environments. It replaces the manual process of creating aQueryClient, callingensureQueryData, and wrapping components in aHydrationBoundary.Key benefits include:
- Concise code: Automates the boilerplate of QueryClient creation and dehydration.
- Parallel fetching: Uses
Promise.allto fetch all provided queries in parallel. - Type safety: Requires
queryKeyto ensure consistency. - Timeout support: Supports a
timeoutprop to throw an error if queries take too long to fetch.
import { QueriesHydration } from '@suspensive/react-query' import { Suspense } from '@suspensive/react' import { userQueryOptions } from './queries' import { UserProfile } from './_components' // Server Component const Page = async ({ userId }: { userId: number }) => { return ( <Suspense fallback={<div>Loading...</div>}> {/* Prefetches userQueryOptions and hydrates UserProfile on the client */} <QueriesHydration queries={[userQueryOptions(userId)]} timeout={1000}> <UserProfile userId={userId} /> </QueriesHydration> </Suspense> ) }Migrate useSuspenseQueries to TanStack Query
TheuseSuspenseQuerieshook in@suspensive/react-queryis deprecated. This functionality is officially supported in TanStack Query v4.40.0+. Developers should migrate by changing the import source from@suspensive/react-queryto@tanstack/react-query.- import { useSuspenseQueries } from '@suspensive/react-query' + import { useSuspenseQueries } from '@tanstack/react-query'Migrate to Suspensive v2
Suspensive v2 focuses on React 18 compatibility and developer experience.
Critical Requirement: React 18.0 or later is required because the library now uses the native
useSyncExternalStorehook.Key Changes and Features:
- Native React 18 APIs: Updated to leverage native Suspense-related features.
queryOptions: Introduced for improved type safety and query management.clientOnlyprop: Added toSuspenseas a replacement forSuspense.CSROnly.- DevMode: Added for enhanced debugging.
- Naming Conventions: Aligned with TanStack Query v5.
- Deprecations:
AsyncBoundaryis deprecated in favor of a cleaner API design.
Install @suspensive/jotai
Install the latest stable version of@suspensive/jotaivia npm. The library requires React^18or^19and Jotai^2. It is compatible with modern browsers including Chrome >= 51, Firefox >= 53, Edge >= 18, Safari >= 11, iOS >= 11, and Opera >= 38.npm install @suspensive/jotaiPerform declarative data fetching with SuspenseQuery
Using@suspensive/react-query, you can fetch data as JSX using the<SuspenseQuery>component. This removes the need foruseSuspenseQueryhooks or splitting components to handle data fetching at the same depth as the UI.<ErrorBoundary fallback={<ErrorUI />}> <Suspense fallback={<Skeleton />}> <SuspenseQuery {...userQueryOptions()}> {({ data: user }) => <UserProfile user={user} />} </SuspenseQuery> </Suspense> </ErrorBoundary>Migrate from React Class Component Error Boundaries
Replace complex class-based error boundaries (usinggetDerivedStateFromErrorandcomponentDidCatch) with the declarative<ErrorBoundary/>component. Use theonErrorprop to replacecomponentDidCatchlogic.import { ErrorBoundary } from '@suspensive/react' const SuspensiveExample = () => ( <ErrorBoundary fallback={({ error, reset }) => <FallbackComponent error={error} reset={reset} />} onError={(error, errorInfo) => logErrorToService(error, errorInfo)} > <YourComponent /> </ErrorBoundary> )