Loading and Displaying Projects
Loading and Displaying Projects
~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
WITH QueryClient (chapter 73) and apiClient (chapter 74) in place, the FIRST real component can NOW be built: a project list.
Defining the type
export interface Project {
'@id': string;
id: number;
name: string;
description: string | null;
priority: number;
isRecent: boolean;
createdAt: string;
}
export interface ProjectCollection {
'hydra:member': Project[];
'hydra:totalItems': number;
}Written MANUALLY, MATCHING project:read (chapter 23) – chapter 80 LATER REPLACES this with AUTOMATICALLY generated types; for THIS chapter, the manual variant is enough to understand the STRUCTURE.
Writing a custom hook
import { useQuery } from '@tanstack/react-query';
import { apiClient } from '../api/client';
import type { ProjectCollection } from '../types/project';
export function useProjects() {
return useQuery({
queryKey: ['projects'],
queryFn: async () => {
const response = await apiClient.get<ProjectCollection>('/projects');
return response.data;
},
});
}queryKey: ['projects'] UNIQUELY identifies this query in the cache – EVERY component calling useProjects() SHARES the SAME cache entry, instead of EACH sending its OWN request.
Building the component
import { useProjects } from '../hooks/useProjects';
function ProjectListPage() {
const { data, isPending, isError, error } = useProjects();
if (isPending) {
return <p>Loading projects...</p>;
}
if (isError) {
return <p>Error: {error.message}</p>;
}
return (
<ul>
{data['hydra:member'].map((project) => (
<li key={project.id}>
{project.name} (priority: {project.priority})
</li>
))}
</ul>
);
}
export default ProjectListPage;isPending/isError/data/error is FULLY handled by TanStack Query – NO custom useState loading state needed, EXACTLY the difference from chapter 8.
Achtung: key={project.id} uses the DATABASE id, NOT the @id IRI – React keys only need to be UNIQUE within the list, the shorter numeric id is COMPLETELY sufficient for that.
Tipp: WITHOUT authentication, this call FAILS (chapter 55: only logged-in users see THEIR projects) – THIS chapter demonstrates the PATTERN, chapters 76-77 add the STILL missing authentication, so the list ACTUALLY shows data.