Skip to content

Commit 16736de

Browse files
committed
add deferred data loading to tanstack router/start examples
1 parent 0b250a3 commit 16736de

File tree

34 files changed

+1309
-603
lines changed

34 files changed

+1309
-603
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ This repository explores data fetching across multiple meta-frameworks and libra
5858
- **Astro** - Multi-framework static site generator with server rendering
5959
- **TanStack Router** - Type-safe routing with built-in data loading
6060
- **TanStack Start** - Full-stack React framework built on TanStack Router
61-
- **SvelteKit** - *bonus* Full-stack Svelte framework for comparison
61+
- **SvelteKit** - _bonus_ Full-stack Svelte framework for comparison
6262

6363
## Getting Started
6464

apps/1-csr/1-1-vite-react-router-componentdidmount/README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This example demonstrates legacy React data fetching patterns using class compon
1414
## Code Examples
1515

1616
### Basic Data Fetching in componentDidMount
17+
1718
```tsx
1819
// HomePage.tsx:53-55
1920
componentDidMount() {
@@ -23,7 +24,7 @@ componentDidMount() {
2324
// HomePage.tsx:32-51
2425
fetchPosts = async () => {
2526
const { posts } = this.state;
26-
27+
2728
if (!posts.length) {
2829
this.setState({ isLoadingPosts: true });
2930
}
@@ -44,6 +45,7 @@ fetchPosts = async () => {
4445
```
4546

4647
### Refetching on Route Parameter Changes
48+
4749
```tsx
4850
// PostPage.tsx:83-89
4951
componentDidUpdate(prevProps: PostPageProps) {
@@ -56,6 +58,7 @@ componentDidUpdate(prevProps: PostPageProps) {
5658
```
5759

5860
### Manual State Management Pattern
61+
5962
```tsx
6063
// PostPage.tsx:17-42
6164
interface HomePageState {
@@ -71,4 +74,4 @@ state: HomePageState = {
7174
isErrorLoadingPosts: false,
7275
isFetchingPosts: false,
7376
};
74-
```
77+
```

apps/1-csr/1-2-vite-react-router-useeffect/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This example demonstrates the native React hooks approach to data fetching using
1616
## Code Examples
1717

1818
### Basic Data Fetching with useEffect
19+
1920
```tsx
2021
// HomePage.tsx:45-47
2122
useEffect(() => {
@@ -44,6 +45,7 @@ const fetchPosts = async () => {
4445
```
4546

4647
### useState for State Management
48+
4749
```tsx
4850
// HomePage.tsx:18-22
4951
const [posts, setPosts] = useState<IPost[]>([]);
@@ -53,6 +55,7 @@ const [isFetchingPosts, setIsFetchingPosts] = useState(false);
5355
```
5456

5557
### Using useParams for Route Parameters
58+
5659
```tsx
5760
// PostPage.tsx:23
5861
const { id: postId } = useParams();
@@ -66,4 +69,5 @@ useEffect(() => {
6669
```
6770

6871
### Problem: Missing Dependency Arrays
69-
Notice this example has a potential issue - the useEffect calls functions that depend on `postId` but doesn't include dependencies, which could cause stale closure problems when route parameters change.
72+
73+
Notice this example has a potential issue - the useEffect calls functions that depend on `postId` but doesn't include dependencies, which could cause stale closure problems when route parameters change.

apps/1-csr/1-3-vite-react-router-react-query/README.md

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This example demonstrates professional-grade data fetching using TanStack Query
1515
## Code Examples
1616

1717
### Basic Query Usage
18+
1819
```tsx
1920
// HomePage.tsx:19-32
2021
const {
@@ -33,6 +34,7 @@ const {
3334
```
3435

3536
### Dependent Queries with Enabled Option
37+
3638
```tsx
3739
// PostPage.tsx:41-54
3840
const {
@@ -50,6 +52,7 @@ const {
5052
```
5153

5254
### Background Refetching
55+
5356
```tsx
5457
// PostPage.tsx:57-72
5558
const {
@@ -61,14 +64,17 @@ const {
6164
} = useQuery({
6265
queryKey: ["posts", postId, "comments"],
6366
queryFn: async () => {
64-
const response = await fetch(`http://localhost:3300/posts/${postId}/comments`);
67+
const response = await fetch(
68+
`http://localhost:3300/posts/${postId}/comments`,
69+
);
6570
return response.json() as Promise<IComment[]>;
6671
},
6772
refetchInterval: 10000, // Auto-refetch every 10 seconds
6873
});
6974
```
7075

7176
### Mutations with Optimistic Updates
77+
7278
```tsx
7379
// PostPage.tsx:108-160
7480
const { mutate: postComment, isPending: isPostingComment } = useMutation({
@@ -82,20 +88,30 @@ const { mutate: postComment, isPending: isPostingComment } = useMutation({
8288
},
8389
// Optimistic update - UI changes immediately
8490
onMutate: async (newComment) => {
85-
await queryClient.cancelQueries({ queryKey: ["posts", postId, "comments"] });
86-
87-
const previousComments = queryClient.getQueryData(["posts", postId, "comments"]);
88-
91+
await queryClient.cancelQueries({
92+
queryKey: ["posts", postId, "comments"],
93+
});
94+
95+
const previousComments = queryClient.getQueryData([
96+
"posts",
97+
postId,
98+
"comments",
99+
]);
100+
89101
// Update UI optimistically
90-
queryClient.setQueryData(["posts", postId, "comments"],
91-
(oldComments: any) => [...oldComments, newComment]
102+
queryClient.setQueryData(
103+
["posts", postId, "comments"],
104+
(oldComments: any) => [...oldComments, newComment],
92105
);
93-
106+
94107
return { previousComments };
95108
},
96109
// Rollback on error
97110
onError: (err, _newComment, context) => {
98-
queryClient.setQueryData(["posts", postId, "comments"], context?.previousComments);
111+
queryClient.setQueryData(
112+
["posts", postId, "comments"],
113+
context?.previousComments,
114+
);
99115
},
100116
// Refresh data after success/error
101117
onSettled: () => {
@@ -105,11 +121,12 @@ const { mutate: postComment, isPending: isPostingComment } = useMutation({
105121
```
106122

107123
### Query Invalidation for Cache Management
124+
108125
```tsx
109126
// PostPage.tsx:98-102
110127
onSettled: () => {
111128
queryClient.invalidateQueries({
112129
queryKey: ["posts", postId, "comments"],
113130
}); // Refresh comments after deletion
114131
},
115-
```
132+
```

apps/1-csr/1-4-vite-react-router-react-query-hooks/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This example demonstrates how to organize React Query code into reusable custom
1515
## Code Examples
1616

1717
### Custom Hook Structure
18+
1819
```tsx
1920
// hooks/useGetPosts.ts:7-22
2021
export const getPostsQueryKey = () => [ENDPOINT];
@@ -40,6 +41,7 @@ export function prefetchPosts(queryClient: QueryClient) {
4041
```
4142

4243
### Using Custom Hooks in Components
44+
4345
```tsx
4446
// pages/HomePage.tsx:48-49
4547
function HomePagePosts() {
@@ -49,6 +51,7 @@ function HomePagePosts() {
4951
```
5052

5153
### Query Key Management
54+
5255
```tsx
5356
// hooks/useGetPostComments.ts:7
5457
export const getPostCommentsQueryKey = (postId: string) => [ENDPOINT(postId)];
@@ -63,14 +66,12 @@ onSettled: () => {
6366
```
6467

6568
### Suspense-Based Loading with Error Boundaries
69+
6670
```tsx
6771
// pages/HomePage.tsx:14-25
6872
<QueryErrorResetBoundary>
6973
{({ reset }) => (
70-
<ErrorBoundary
71-
fallbackRender={() => <HomePageError />}
72-
onReset={reset}
73-
>
74+
<ErrorBoundary fallbackRender={() => <HomePageError />} onReset={reset}>
7475
<Suspense fallback={<HomePageSkeleton />}>
7576
<HomePagePosts />
7677
</Suspense>
@@ -80,6 +81,7 @@ onSettled: () => {
8081
```
8182

8283
### Dependent Queries with Enabled Option
84+
8385
```tsx
8486
// hooks/useGetUser.ts:19-24
8587
export function useGetUser(userId?: number) {
@@ -99,4 +101,4 @@ While this custom hooks pattern was popular, the newer `queryOptions` pattern (s
99101
- **Easier composition and reuse**
100102
- **Official recommendation from TanStack Query team**
101103

102-
This example remains valuable for understanding how React Query code organization evolved and may still be found in existing codebases.
104+
This example remains valuable for understanding how React Query code organization evolved and may still be found in existing codebases.

apps/1-csr/1-5-vite-react-router-react-query-query-options/README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This example demonstrates the modern, recommended approach to organizing React Q
1515
## Code Examples
1616

1717
### Basic queryOptions Definition
18+
1819
```tsx
1920
// queries/posts.ts:7-13
2021
export const postsQueryOptions = queryOptions({
@@ -27,6 +28,7 @@ export const postsQueryOptions = queryOptions({
2728
```
2829

2930
### Parameterized queryOptions
31+
3032
```tsx
3133
// queries/posts.ts:16-23
3234
export const postQueryOptions = (postId: string) =>
@@ -40,6 +42,7 @@ export const postQueryOptions = (postId: string) =>
4042
```
4143

4244
### Using queryOptions with Different Hooks
45+
4346
```tsx
4447
// pages/HomePage.tsx:50 - With useSuspenseQuery
4548
const { data: posts } = useSuspenseQuery(postsQueryOptions);
@@ -49,15 +52,21 @@ const { data: post, isLoading, isError } = useQuery(postQueryOptions(postId!));
4952
```
5053

5154
### Extending queryOptions for Dependent Queries
55+
5256
```tsx
5357
// pages/PostPage.tsx:42-45
54-
const { data: user, isLoading: isLoadingUser, isError: isErrorLoadingUser } = useQuery({
58+
const {
59+
data: user,
60+
isLoading: isLoadingUser,
61+
isError: isErrorLoadingUser,
62+
} = useQuery({
5563
...userQueryOptions(post?.userId!), // Spread the base options
5664
enabled: !!post?.userId, // Add additional configuration
5765
});
5866
```
5967

6068
### Query Key Access for Cache Management
69+
6170
```tsx
6271
// pages/PostPage.tsx:81-84
6372
onSettled: () => {
@@ -68,6 +77,7 @@ onSettled: () => {
6877
```
6978

7079
### Complex Query Options with Additional Configuration
80+
7181
```tsx
7282
// queries/comments.ts:7-15
7383
export const postCommentsQueryOptions = (postId: string) =>
@@ -84,23 +94,27 @@ export const postCommentsQueryOptions = (postId: string) =>
8494
## Advantages Over Custom Hooks Pattern
8595

8696
**1. Better TypeScript Support**
97+
8798
- Improved type inference
8899
- Consistent typing across different hooks
89100
- Better intellisense and autocomplete
90101

91102
**2. More Flexible**
103+
92104
- Works with any React Query hook (`useQuery`, `useSuspenseQuery`, `useInfiniteQuery`, etc.)
93105
- Easy to extend with additional options
94106
- Framework-agnostic definitions
95107

96108
**3. Official Recommendation**
109+
97110
- Current best practice from TanStack team
98111
- Future-proof approach
99112
- Better documentation and community support
100113

101114
**4. Cleaner Code**
115+
102116
- Less boilerplate than custom hooks
103117
- More declarative approach
104118
- Easier to test and mock
105119

106-
This is the current recommended pattern for organizing React Query code in modern applications.
120+
This is the current recommended pattern for organizing React Query code in modern applications.

0 commit comments

Comments
 (0)