Skip to content

feat: Svelte 5 API proposal #8852

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 27 commits into
base: svelte-5-adapter
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8c9ce99
WIP: Svelte 5 adapter (#6981)
zhihengGet Jul 26, 2024
647cbf9
Merge remote-tracking branch 'origin' into svelte-5-adapter-notes
elliott-with-the-longest-name-on-github Mar 23, 2025
3e60f15
feat: Draft proposal
elliott-with-the-longest-name-on-github Mar 25, 2025
cd2d81f
Merge remote-tracking branch 'origin' into svelte-5-adapter-derived-by
elliott-with-the-longest-name-on-github Mar 25, 2025
fec1a0d
chore: Improve reactive containers
elliott-with-the-longest-name-on-github Mar 25, 2025
5b359ed
ci: apply automated fixes
autofix-ci[bot] Mar 25, 2025
8325a7b
oops
elliott-with-the-longest-name-on-github Mar 25, 2025
a6917da
Merge branch 'svelte-5-adapter-derived-by' of github.com:elliott-with…
elliott-with-the-longest-name-on-github Mar 25, 2025
4c93461
fix: Update API, add a bunch of tests
elliott-with-the-longest-name-on-github Apr 2, 2025
07ab8dd
Merge remote-tracking branch 'origin' into svelte-5-adapter-derived-by
elliott-with-the-longest-name-on-github Apr 2, 2025
c35a54f
merge main
elliott-with-the-longest-name-on-github Apr 2, 2025
cb173e2
fix: use const
elliott-with-the-longest-name-on-github Apr 2, 2025
b7dda3d
more tests
elliott-with-the-longest-name-on-github Apr 2, 2025
cc54952
feat: More tests, back to thunks, fixed svelte-query-persist-client
elliott-with-the-longest-name-on-github Apr 3, 2025
6e73278
feat: More tests and examples!
elliott-with-the-longest-name-on-github Apr 8, 2025
9fdbcad
Merge remote-tracking branch 'upstream/main' into svelte-5-adapter-de…
elliott-with-the-longest-name-on-github Apr 8, 2025
14620d1
lockfile
elliott-with-the-longest-name-on-github Apr 15, 2025
7e542cd
Merge remote-tracking branch 'origin/svelte-5-adapter' into svelte-5-…
elliott-with-the-longest-name-on-github Apr 15, 2025
ba92c7f
fixes
elliott-with-the-longest-name-on-github Apr 15, 2025
dffbdc7
Fix current CI errors
lachlancollins Apr 20, 2025
2452ce9
More small fixes/tweaks
lachlancollins Apr 20, 2025
d0bbe8c
Remove test.only
lachlancollins Apr 20, 2025
fd399fb
ci: apply automated fixes
autofix-ci[bot] Apr 20, 2025
258d992
Fix pnpm-lock, fix import order
lachlancollins Apr 20, 2025
6af7b18
update main docs
elliott-with-the-longest-name-on-github Apr 30, 2025
855fd47
feat: More tests
elliott-with-the-longest-name-on-github May 1, 2025
022cd6b
ci: apply automated fixes
autofix-ci[bot] May 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,6 @@
{
"label": "SSR & SvelteKit",
"to": "framework/svelte/ssr"
},
{
"label": "Reactivity",
"to": "framework/svelte/reactivity"
}
]
},
Expand Down
2 changes: 1 addition & 1 deletion docs/framework/svelte/devtools.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Place the following code as high in your Svelte app as you can. The closer it is

### Options

- `initialIsOpen: Boolean`
- `initialIsOpen: boolean`
- Set this `true` if you want the dev tools to default to being open
- `buttonPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "relative"`
- Defaults to `bottom-right`
Expand Down
2 changes: 0 additions & 2 deletions docs/framework/svelte/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ title: Installation

You can install Svelte Query via [NPM](https://npmjs.com).

> v5 is currently available as a release-candidate. We don't anticipate any major API changes from here on out. We encourage you to try it out and report any issues you find.

### NPM

```bash
Expand Down
19 changes: 10 additions & 9 deletions docs/framework/svelte/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ Then call any function (e.g. createQuery) from any component:
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'

const query = createQuery({
const query = createQuery(() => ({
queryKey: ['todos'],
queryFn: () => fetchTodos(),
})
}))
</script>

<div>
{#if $query.isLoading}
{#if query.isLoading}
<p>Loading...</p>
{:else if $query.isError}
<p>Error: {$query.error.message}</p>
{:else if $query.isSuccess}
{#each $query.data as todo}
{:else if query.isError}
<p>Error: {query.error.message}</p>
{:else if query.isSuccess}
{#each query.data as todo}
<p>{todo.title}</p>
{/each}
{/if}
Expand All @@ -62,6 +62,8 @@ Svelte Query offers useful functions and components that will make managing serv
- `useQueryClient`
- `useIsFetching`
- `useIsMutating`
- `useMutationState`
- `useIsRestoring`
- `useHydrate`
- `<QueryClientProvider>`
- `<HydrationBoundary>`
Expand All @@ -70,5 +72,4 @@ Svelte Query offers useful functions and components that will make managing serv

Svelte Query offers an API similar to React Query, but there are some key differences to be mindful of.

- Many of the functions in Svelte Query return a Svelte store. To access values on these stores reactively, you need to prefix the store with a `$`. You can learn more about Svelte stores [here](https://learn.svelte.dev/tutorial/writable-stores).
- If your query or mutation depends on variables, you must use a store for the options. You can read more about this [here](../reactivity).
- The arguments to the `create*` functions must be wrapped in a function to preserve reactivity.
49 changes: 0 additions & 49 deletions docs/framework/svelte/reactivity.md

This file was deleted.

8 changes: 4 additions & 4 deletions docs/framework/svelte/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ export async function load() {

export let data: PageData

const query = createQuery({
const query = createQuery(() => ({
queryKey: ['posts'],
queryFn: getPosts,
initialData: data.posts,
})
}))
</script>
```

Expand Down Expand Up @@ -136,10 +136,10 @@ export async function load({ parent, fetch }) {
import { createQuery } from '@tanstack/svelte-query'

// This data is cached by prefetchQuery in +page.ts so no fetch actually happens here
const query = createQuery({
const query = createQuery(() => ({
queryKey: ['posts'],
queryFn: async () => (await fetch('/api/posts')).json(),
})
}))
</script>
```

Expand Down
26 changes: 18 additions & 8 deletions examples/svelte/auto-refetching/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

const client = useQueryClient()

const endpoint = 'http://localhost:5173/api/data'
const endpoint = '/api/data'

const todos = createQuery<{ items: string[] }>(() => ({
queryKey: ['refetch'],
Expand All @@ -21,7 +21,9 @@

const addMutation = createMutation(() => ({
mutationFn: (value: string) =>
fetch(`${endpoint}?add=${value}`).then((r) => r.json()),
fetch(`${endpoint}?add=${encodeURIComponent(value)}`).then((r) =>
r.json(),
),
onSuccess: () => client.invalidateQueries({ queryKey: ['refetch'] }),
}))

Expand All @@ -31,7 +33,7 @@
}))
</script>

<h1>Auto Refetch with stale-time set to 1s</h1>
<h1>Auto Refetch with stale-time set to {(intervalMs / 1000).toFixed(2)}s</h1>

<p>
This example is best experienced on your own machine, where you can open
Expand Down Expand Up @@ -86,14 +88,22 @@
<button onclick={() => clearMutation.mutate(undefined)}> Clear All </button>
</div>
{/if}
{#if todos.isFetching}
<div style="color:darkgreen; font-weight:700">
'Background Updating...' : ' '
</div>
{/if}

<pre
class={['updating-text', todos.isFetching && 'on']}
style="font-weight:700">Background Updating...</pre>

<style>
li {
text-align: left;
}

.updating-text {
color: transparent;
transition: all 0.3s ease;
}
.updating-text.on {
color: green;
transition: none;
}
</style>
18 changes: 12 additions & 6 deletions examples/svelte/basic/src/lib/Posts.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@
</article>
{/each}
</ul>
{#if posts.isFetching}
<div style="color:darkgreen; font-weight:700">
Background Updating...
</div>
{/if}
<pre
class={['updating-text', posts.isFetching && 'on']}
style="font-weight:700">Background Updating...</pre>
{/if}
</div>
</div>
Expand All @@ -53,8 +51,16 @@
}
a {
display: block;
color: white;
font-size: 1.5rem;
margin-bottom: 1rem;
}

.updating-text {
color: transparent;
transition: all 0.3s ease;
}
.updating-text.on {
color: green;
transition: none;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,6 @@
.card {
background-color: #111;
margin-bottom: 1rem;
color: rgba(255, 255, 255, 0.87);
}
</style>
2 changes: 1 addition & 1 deletion examples/svelte/optimistic-updates/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

const client = useQueryClient()

const endpoint = 'http://localhost:5173/api/data'
const endpoint = '/api/data'

const fetchTodos = async (): Promise<Todos> =>
await fetch(endpoint).then((r) => r.json())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type Todo = {
text: string
}

const items: Todo[] = []
const items: Array<Todo> = []

/** @type {import('./$types').RequestHandler} */
export const GET: RequestHandler = async (req) => {
Expand Down
3 changes: 1 addition & 2 deletions examples/svelte/playground/src/routes/AddTodo.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
let name = $state('')

const postTodo = async ({ name, notes }: Omit<Todo, 'id'>) => {
console.info('postTodo', { name, notes })
return new Promise((resolve, reject) => {
setTimeout(
() => {
Expand All @@ -31,7 +30,7 @@
}
const todo = { name, notes, id: id.value }
id.value = id.value + 1
list.value = [...list.value, todo]
list.value.push(todo)
resolve(todo)
},
queryTimeMin.value +
Expand Down
2 changes: 1 addition & 1 deletion examples/svelte/playground/src/routes/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

<button
onclick={() => {
views.value = [...views.value, '']
views.value.push('')
}}
>
Add Filter List
Expand Down
17 changes: 11 additions & 6 deletions examples/svelte/ssr/src/lib/Posts.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@
</article>
{/each}
</ul>
{#if posts.isFetching}
<div style="color:darkgreen; font-weight:700">
Background Updating...
</div>
{/if}
<pre
class={['updating-text', posts.isFetching && 'on']}
style="font-weight:700">Background Updating...</pre>
{/if}
</div>
</div>
Expand All @@ -53,8 +51,15 @@
}
a {
display: block;
color: white;
font-size: 1.5rem;
margin-bottom: 1rem;
}
.updating-text {
color: transparent;
transition: all 0.3s ease;
}
.updating-text.on {
color: green;
transition: none;
}
</style>
2 changes: 1 addition & 1 deletion examples/svelte/ssr/src/routes/+layout.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { browser } from '$app/environment'
import { QueryClient } from '@tanstack/svelte-query'
import type { LayoutLoad } from './$types'
import { browser } from '$app/environment'

export const load: LayoutLoad = () => {
const queryClient = new QueryClient({
Expand Down
2 changes: 1 addition & 1 deletion examples/svelte/ssr/src/routes/+page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { api } from '$lib/api'
import type { PageLoad } from './$types'
import { api } from '$lib/api'

export const load: PageLoad = async ({ parent, fetch }) => {
const { queryClient } = await parent()
Expand Down
2 changes: 1 addition & 1 deletion examples/svelte/ssr/src/routes/[postId]/+page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { api } from '$lib/api'
import type { PageLoad } from './$types'
import { api } from '$lib/api'

export const load: PageLoad = async ({ parent, fetch, params }) => {
const { queryClient } = await parent()
Expand Down
3 changes: 1 addition & 2 deletions examples/svelte/star-wars/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
<h2 class="text-4xl">React Query Demo</h2>
<p>Using the Star Wars API</p>
<p>
(Built by <a href="https://twitter.com/Brent_m_Clark">@Brent_m_Clark</a>
)
(Built by <a href="https://twitter.com/Brent_m_Clark">@Brent_m_Clark</a>)
</p>
<section>
<h5 class="text-2xl">Why React Query?</h5>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@
import { createQuery } from '@tanstack/svelte-query'
import Homeworld from './Homeworld.svelte'
import Film from './Film.svelte'

let { data } = $props()
import { page } from '$app/state'

const getCharacter = async () => {
const res = await fetch(
`https://swapi.dev/api/people/${data.params.characterId}/`,
`https://swapi.dev/api/people/${page.params.characterId}/`,
)
return await res.json()
}

const query = createQuery(() => ({
queryKey: ['character', data.params.characterId],
queryKey: ['character', page.params.characterId],
queryFn: getCharacter,
}))
</script>
Expand Down

This file was deleted.

Loading
Loading