@hateoas-ts/resource-react
v1.4.0
Published
[](https://www.npmjs.com/package/@hateoas-ts/resource-react) [](https://www.npmjs.com/package/@hateoas
Readme
@hateoas-ts/resource-react
React hooks for type-safe HATEOAS API navigation. Built on top of @hateoas-ts/resource.
Installation
npm install @hateoas-ts/resource-react @hateoas-ts/resourceQuick Start
1. Set Up Provider
import { createClient } from '@hateoas-ts/resource';
import { ResourceProvider } from '@hateoas-ts/resource-react';
const client = createClient({ baseURL: 'https://api.example.com' });
function App() {
return (
<ResourceProvider client={client}>
<YourApp />
</ResourceProvider>
);
}2. Define Entity Types
import { Entity, Collection } from '@hateoas-ts/resource';
export type User = Entity<{ id: string; name: string; email: string }, { self: User; conversations: Collection<Conversation> }>;
export type Conversation = Entity<{ id: string; title: string }, { self: Conversation }>;3. Use Hooks
import { useResource, useInfiniteCollection, useClient } from '@hateoas-ts/resource-react';
function UserProfile({ userId }: { userId: string }) {
const client = useClient();
const userResource = client.go<User>(`/api/users/${userId}`);
// Fetch single resource
const { loading, error, data } = useResource(userResource);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>Welcome, {data.name}!</div>;
}
function ConversationList({ userId }: { userId: string }) {
const client = useClient();
const userResource = client.go<User>(`/api/users/${userId}`);
// Fetch paginated collection with infinite scroll
const { items, loading, hasNextPage, loadNextPage } = useInfiniteCollection(userResource.follow('conversations'));
return (
<div>
{items.map((item) => (
<div key={item.data.id}>{item.data.title}</div>
))}
{hasNextPage && (
<button onClick={loadNextPage} disabled={loading}>
{loading ? 'Loading...' : 'Load More'}
</button>
)}
</div>
);
}API Reference
Provider
| Export | Description |
| ------------------ | ----------------------------------- |
| ResourceProvider | Context provider for HATEOAS client |
Hooks
| Hook | Description |
| --------------------------------- | ----------------------------------------------- |
| useClient() | Access the client instance |
| useResource(resource) | Fetch a single resource |
| useInfiniteCollection(resource) | Fetch paginated collection with infinite scroll |
React 19 Suspense Hooks
| Hook | Description |
| ----------------------------------------- | -------------------------------------- |
| useSuspenseResource(resource) | Suspense-enabled single resource fetch |
| useSuspenseInfiniteCollection(resource) | Suspense-enabled infinite scroll |
Suspense Example (React 19+)
import { Suspense } from 'react';
import { useSuspenseResource, useClient } from '@hateoas-ts/resource-react';
function UserProfile({ userId }: { userId: string }) {
const client = useClient();
const { data } = useSuspenseResource(client.go<User>(`/api/users/${userId}`));
// No loading check - suspends until ready
return <div>Welcome, {data.name}!</div>;
}
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<UserProfile userId="123" />
</Suspense>
);
}Return Types
useResource / useSuspenseResource
{
loading: boolean; // Loading state (useResource only)
error: Error | null; // Error if request failed
data: T['data']; // Entity data
resourceState: State<T>; // Full state with links
resource: Resource<T>; // Resource for further navigation
}useInfiniteCollection / useSuspenseInfiniteCollection
{
items: State<Element>[]; // Accumulated collection items
loading: boolean; // Loading state (non-suspense only)
isLoadingMore: boolean; // Loading more pages (suspense only)
hasNextPage: boolean; // More pages available
error: Error | null; // Error if request failed
loadNextPage: () => void; // Load next page
}Related
@hateoas-ts/resource- Core HATEOAS client
License
MIT
