Background image

Product Updates

React Hooks: TypeScript SDKs with TanStack React Query Support

Georges Haidar

Georges Haidar

December 6, 2024

Featured blog post image
Success Icon

Preview Availability

Now in preview! Enable React hook generation for your TypeScript SDKs through the Speakeasy CLI. Check out our getting started guide to try it today.

Today, we’re excited to announce first-class support for React hooks in our TypeScript SDKs. This new generation feature builds on top of our standalone functions work and TanStack Query (opens in a new tab) (formerly React Query) to provide seamless integration between your API and React applications.

We think this feature is going supercharge teams to build awesome React applications against their APIs in the fewest steps possible.

Used in roughly 1 in 6 React projects today, TanStack Query has become the de-facto standard for managing server state in React applications. Our new generator wraps your API operations, utilizing TanStack Query’s powerful caching, synchronization, and data management features to create fully-typed hooks that are ready for use in your React app. Here are the key features you get out of the box:

  • Full type safety from your API through React components
  • Backed by runtime validation with Zod (opens in a new tab) so you can trust your types
  • Great tree-shaking performance so you only bundle the hooks and SDK code you use
  • Automatic cache management with smart invalidation utilities
  • Support for both standard and infinite pagination patterns
  • Integration with server-side rendering, React Server Components and Suspense
  • Optimistic updates and background refetching
  • Smart request deduplication and request cancellation
profile-view.tsx
import { useActorProfile } from "@speakeasy-api/bluesky/react-query";
function Demo() {
const { data, status, error, isPlaceholderData } = useActorProfile(
{
actor: props.username,
},
{
// All the familiar options from TanStack Query.
enabled: !!props.username && !!didResult.data,
placeholderData: (previousData) => previousData,
},
);
if (status === "loading") {
return <div>Loading...</div>;
}
if (status === "error") {
return <div>Error: {error.message}</div>;
}
const { followersCount = "-", followsCount = "-" } = data;
return (
<div className="inline-flex items-start gap-2 rounded border-zinc-800">
<img
className="w-16 aspect-square rounded-full"
src={data.avatar}
alt={data.displayName}
/>
<div>
<h1 className="text-2xl">{data.displayName}</h1>
<p className="text-muted-foreground">{data.handle}</p>
<p>
<span className="font-semibold">{followersCount}</span>
<span className="text-muted-foreground">followers</span>
</p>
<p>
<span className="font-semibold">{followsCount}</span>
<span className="text-muted-foreground">follows</span>
</p>
</div>
</div>
);
}

End-to-end Type Safety

Our React hooks provide complete type safety from your API definition all the way through to your React components. Request and response types are derived from your OpenAPI specification and validated at runtime, ensuring your application stays in sync with your API contract.

The type-safe interface helps developers catch errors early and enables rich IDE features like autocompletion and inline documentation.

Intelligent Cache Management

Managing cached data is one of the most challenging aspects of building modern web applications. Building on TanStack query, our React hooks handle this complexity for you by generating intelligent cache keys. We then provide utility functions to invalidate specific resources or groups of resources, making it easy to keep your UI in sync with your server state. The cache management system is built to handle common patterns like:

  • Optimistic updates for a snappy UI
  • Background refetching of stale data
  • Smart request deduplication
  • Automatic revalidation after mutations

Support for SSR, RSC, Suspense and more

Our React hooks are designed to work seamlessly with modern React patterns and features. We provide both standard and Suspense-enabled versions of each query hook, letting you choose the right approach for your application.

Additionally, we provide utilities for prefetching data during server-side rendering and in React Server Components that will be immediately available to client components using the hooks.

The hooks also support TanStack Query’s latest features for handling loading states, preventing layout shift, and managing complex data dependencies.

Here’s an example of everything you get for each operation in your SDK:

import {
// Query hooks for fetching data.
useFollowers,
useFollowersSuspense,
// Query hooks suitable for building infinite scrolling or "load more" UIs.
useFollowersInfinite,
useFollowersInfiniteSuspense,
// Utility for prefetching data during server-side rendering and in React
// Server Components that will be immediately available to client components
// using the hooks.
prefetchFollowers,
// Utilities to invalidate the query cache for this query in response to
// mutations and other user actions.
invalidateFollowers,
invalidateAllFollowers,
} from "@speakeasy-api/bluesky/react-query/followers.js";

Pagination Made Simple

We automatically detect pagination patterns in your API and generate appropriate hooks for both traditional pagination and infinite scroll interfaces. The infinite query hooks integrate perfectly with intersection observers for building smooth infinite scroll experiences.

Here’s an example using the infinite query (opens in a new tab) version of a React hook:

import { useInView } from "react-intersection-observer";
import { useActorAuthorFeedInfinite } from "@speakeasy-api/bluesky/react-query/actorAuthorFeed.js";
export function PostsView(props: { did: string }) {
const { data, fetchNextPage, hasNextPage } = useActorAuthorFeedInfinite({
actor: props.did,
});
const { ref } = useInView({
rootMargin: "50px",
onChange(inView) {
if (inView) { fetchNextPage(); }
},
});
return (
<div>
<ul className="space-y-4">
{data?.pages.flatMap((page) => {
return page.result.feed.map((entry) => (
<li key={entry.post.cid}>
<FeedEntry entry={entry.post} />
</li>
));
})}
</ul>
{hasNextPage ? <div ref={ref} /> : null}
</div>
);

Looking Forward

We’re excited to see how the community puts these new features to work. Your feedback is invaluable to us, and we welcome everyone to join us in refining these tools to better serve the React ecosystem.

Try out the new React hooks today by updating your Speakeasy CLI and enabling React hooks generation for your TypeScript SDKs. Check out our documentation to get started.

CTA background illustrations

Speakeasy Changelog

Subscribe to stay up-to-date on Speakeasy news and feature releases.