Skip to content

Commit

Permalink
docs(suspensive.org): add sandpack examples to useSuspenseQuery, useS…
Browse files Browse the repository at this point in the history
…uspenseQueries, and useSuspenseInfiniteQuery (#1003)

# Overview

<!--
    A clear and concise description of what this pr is about.
 -->

Add sandpack examples to useSuspenseQuery, useSuspenseQueries, and
useSuspenseInfiniteQuery.




## PR Checklist

- [x] I did below actions if need

1. I read the [Contributing
Guide](https://github.com/toss/suspensive/blob/main/CONTRIBUTING.md)
2. I added documents and tests.
  • Loading branch information
kangju2000 authored Jun 28, 2024
1 parent c515da6 commit 0991644
Show file tree
Hide file tree
Showing 6 changed files with 522 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Callout } from '@/components'
import { Callout, Sandpack } from '@/components'

# useSuspenseInfiniteQuery

Expand All @@ -18,6 +18,99 @@ const Example = () => {
}
```

<Sandpack>

```tsx PostList.tsx active
import { useSuspenseInfiniteQuery } from '@suspensive/react-query'
import React from 'react'
import { getPosts } from './api'

export const PostList = () => {
const { data, isFetchingNextPage, isFetched, hasNextPage, fetchNextPage } =
useSuspenseInfiniteQuery({
queryKey: ['posts'],
queryFn: ({ pageParam = 1 }) => getPosts(pageParam),
getNextPageParam: (lastPage, allPages) => {
return lastPage.skip + lastPage.limit < lastPage.total ? allPages.length + 1 : undefined
},
})

React.useEffect(() => {
if (!isFetchingNextPage && isFetched) {
window.scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth',
})
}
}, [isFetchingNextPage, isFetched])

return (
<div style={{ display: 'flex', flexDirection: 'column', marginBottom: '100px' }}>
<ol>
{data.pages.map((page, i) => (
<React.Fragment key={i}>
{page.data.map((post) => (
<li key={post.id} style={{ marginBottom: '10px' }}>
{post.title}
</li>
))}
</React.Fragment>
))}
</ol>
<button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage}>
{isFetchingNextPage
? 'Loading more...'
: hasNextPage
? 'Load More'
: 'Nothing more to load'}
</button>
</div>
)
}
```

```tsx Example.tsx
import { Suspense } from '@suspensive/react'
import { PostList } from './PostList'

export const Example = () => {
return (
<Suspense fallback={<div>Loading...</div>}>
<PostList />
</Suspense>
)
}
```

```tsx api.ts
type Post = {
userId: number
id: number
title: string
body: string
}

export const getPosts = async (page: number): Promise<{ data: Post[], page: number, total: number, limit: number, skip: number }> => {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_page=${page}`)

if (!response.ok) {
throw new Error('An error occurred')
}

const data = await response.json()

return {
data,
page,
total: 100,
limit: 10,
skip: (page - 1) * 10,
}
}
```

</Sandpack>

### Motivation

If you turn suspense on in @tanstack/react-query, You can use [useInfiniteQuery](https://tanstack.com/query/v4/docs/react/reference/useInfiniteQuery) with `<Suspense/>` and `<ErrorBoundary/>`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Callout } from '@/components'
import { Callout, Sandpack } from '@/components'

# useSuspenseInfiniteQuery

Expand All @@ -18,6 +18,99 @@ const Example = () => {
}
```

<Sandpack>

```tsx Posts.tsx active
import { useSuspenseInfiniteQuery } from '@suspensive/react-query'
import React from 'react'
import { getPosts } from './api'

export const Posts = () => {
const { data, isFetchingNextPage, isFetched, hasNextPage, fetchNextPage } =
useSuspenseInfiniteQuery({
queryKey: ['posts'],
queryFn: ({ pageParam = 1 }) => getPosts(pageParam),
getNextPageParam: (lastPage, allPages) => {
return lastPage.skip + lastPage.limit < lastPage.total ? allPages.length + 1 : undefined
},
})

React.useEffect(() => {
if (!isFetchingNextPage && isFetched) {
window.scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth',
})
}
}, [isFetchingNextPage, isFetched])

return (
<div style={{ display: 'flex', flexDirection: 'column', marginBottom: '100px' }}>
<ol>
{data.pages.map((page, i) => (
<React.Fragment key={i}>
{page.data.map((post) => (
<li key={post.id} style={{ marginBottom: '10px' }}>
{post.title}
</li>
))}
</React.Fragment>
))}
</ol>
<button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage}>
{isFetchingNextPage
? 'Loading more...'
: hasNextPage
? 'Load More'
: 'Nothing more to load'}
</button>
</div>
)
}
```

```tsx Example.tsx
import { Suspense } from '@suspensive/react'
import { Posts } from './Posts'

export const Example = () => {
return (
<Suspense fallback={<div>Loading...</div>}>
<Posts />
</Suspense>
)
}
```

```tsx api.ts
type Post = {
userId: number
id: number
title: string
body: string
}

export const getPosts = async (page: number): Promise<{ data: Post[], page: number, total: number, limit: number, skip: number }> => {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_page=${page}`)

if (!response.ok) {
throw new Error('An error occurred')
}

const data = await response.json()

return {
data,
page,
total: 100,
limit: 10,
skip: (page - 1) * 10,
}
}
```

</Sandpack>

### 동기

@tanstack/react-query에서 suspense 옵션을 사용하면, [useInfiniteQuery](https://tanstack.com/query/v4/docs/react/reference/useInfiniteQuery)`<Suspense/>`, `<ErrorBoundary/>`와 함께 사용할 수 있습니다.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Callout } from '@/components'
import { Callout, Sandpack } from '@/components'

# useSuspenseQueries

Expand All @@ -21,6 +21,103 @@ const Example = () => {
}
```

<Sandpack>

```tsx Post.tsx active
import { useSuspenseQueries } from '@suspensive/react-query'
import { getPost, getComments } from './api'

export const Post = ({ postId }: { postId: number }) => {
const [postQuery, commentQuery] = useSuspenseQueries({
queries: [
{ queryKey: ['posts', postId], queryFn: () => getPost(postId) },
{ queryKey: ['comments', postId], queryFn: () => getComments(postId) },
],
})

return (
<div>
<h1>{postQuery.data.title}</h1>
<p>{postQuery.data.body}</p>
<h2>Comments</h2>
<ul>
{commentQuery.data.map((comment) => (
<li key={comment.id}>{comment.body}</li>
))}
</ul>
</div>
)
}

```

```tsx Example.tsx
import { Suspense } from '@suspensive/react'
import React from 'react'
import { Post } from './Post'

export const Example = () => {
const [postId, setPostId] = React.useState(1)

return (
<div>
<button onClick={() => setPostId((prev) => prev - 1)} disabled={postId === 1}>
Previous Post
</button>
<button onClick={() => setPostId((prev) => prev + 1)} disabled={postId === 100}>
Next Post
</button>
<Suspense fallback={<div>Loading...</div>}>
<Post postId={postId} />
</Suspense>
</div>
)
}
```

```tsx /api.ts
type Post = {
userId: number
id: number
title: string
body: string
}

export const getPost = async (id: number): Promise<Post> => {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)

if (!response.ok) {
throw new Error('An error occurred')
}

const data = await response.json()

return data
}

type Comment = {
postId: number
id: number
name: string
email: string
body: string
}

export const getComments = async (postId: number): Promise<Comment[]> => {
const response = await fetch(`https://jsonplaceholder.typicode.com/comments?postId=${postId}`)

if (!response.ok) {
throw new Error('An error occurred')
}

const data = await response.json()

return data
}
```

</Sandpack>

### Motivation

You can use [useQueries](https://tanstack.com/query/v4/docs/react/reference/useQueries) with `<Suspense/>` and `<ErrorBoundary/>` by using the suspense option of @tanstack/react-query useQueries.
Expand Down
Loading

0 comments on commit 0991644

Please sign in to comment.