Optimistic UI is not easy...but it can be easier then ever in SvelteKit with Optimistikit!
npm install optimistikitOptimistic UI is not easy...but it can be easier then ever in SvelteKit with Optimistikit!
> Warning
>
> This package is meant to be used with Svelte-Kit as the name suggest. Because it uses api that are only present in Svelte-Kit it will not work in your normal svelte project.

!npm
!npm
Contributions are always welcome!
For the moment there's no code of conduct neither a contributing guideline but if you found a problem or have an idea feel free to open an issue
If you want the fastest way to open a PR try out Codeflow

Install optimistikit with npm
``bash`
npm install optimistikit@latest
The concept behind optimistikit is quite straightforward. Instead of using the data props from SvelteKit you can call the function optimistikit and get back a function to call whenever data changes and an action to apply to all of your forms.
Imagine you have this +page.server.ts
`ts
export async function load() {
const comments = await db.select(comments);
return {
comments,
};
}
export const actions = {
async add({ request }) {
const formData = await request.formData();
const new_comment = formData.get('comment');
if (new_comment) {
await db.insert(comments).values({
content: new_comment,
});
}
},
};
`
and this +page.svelte
`svelte
if you want to optimistically add the comment using
optimistikit you would need the following updated to +page.svelte`svelte
use:enhance={(data, { formData }) => {
const new_comment = formData.get('comment');
if (new_comment) {
// just mutate data
data.comments.push({
content: new_comment,
});
}
}}
method="post"
action="?/add"
>
{#each optimistic_data.comments as comment}
- {comment.content}
{/each}
`$3
Sometimes the resource that you are updating on the server is always the same resource (eg. updating a comment). When that's the case we want to cancel every concurrent request. You can do this by adding an unique
data-key attribute to the form.`ts
export async function load() {
const comments = await db.select(comments);
return {
comments,
};
}export const actions = {
// other actions
async edit({ request }) {
const formData = await request.formData();
const new_comment = formData.get('comment');
const id = formData.get('id');
if (new_comment && id) {
await db
.update(comments)
.values({
content: new_comment,
})
.where({
id,
});
}
},
};
`and this is the
+page.svelte`svelte
{#each optimistic_data.comments as comment}
method="post"
action="?/edit"
data-key="edit-comment-{comment.id}"
use:enhance={(data, { formData }) => {
const new_comment = formData.get('comment');
const id = formData.get('id');
if (new_comment && id) {
const comment = data.comments.find((comment) => comment.id === id);
// just mutate
data
comment.content = new_comment;
}
}}
>
{/each}
`$3
If you have a form in a nested component it can be tedious to pass either
data or the enhance action around. To solver this problem there's another export from optimistikit that allows you to grab the action directly`svelte
use:enhance={(data) => {
// your logic
}}
>
`$3
The function
optimistikit can optionally receive an object as argument where you can specify two values:-
key: a string that allows you to have different actions/stores in the same route. Most of the times you will probably not need this since specifying a key also means that the updates from the forms will involve only the state returned from that specific optimistikit function.
- enhance: some libraries like superforms provide a custom enhance function that is different from the one provided by SvelteKit. To allow you to use this libraries together with optimistikit you can pass a custom enhance function. It's important for this function to have the same signature as the sveltekit one.What about svelte 4?
If you are using
svelte@4 you really should upgrade to svelte@5...but if you can't you can use the legacy tag of this library that uses a store and has a slightly different and less ergonomic API.You can install it like this:
`bash
npm i optimistikit@legacy
``Check the documentation here!