GithubHelp home page GithubHelp logo

consoletvs / sswr Goto Github PK

View Code? Open in Web Editor NEW
226.0 3.0 11.0 132 KB

๐Ÿ”ฅ Svelte stale while revalidate (SWR) data fetching strategy

License: MIT License

TypeScript 93.49% JavaScript 6.51%
svelte swr stale-while-revalidate fetch javascript typescript

sswr's Introduction

SSWR (Svelte Stale While Revalidate)

Svelte stale while revalidate (SWR) data fetching strategy

Table of Contents

Introduction

Quote from vercel's SWR for react:

The name โ€œSWRโ€ is derived from stale-while-revalidate, a HTTP cache invalidation strategy popularized by HTTP RFC 5861. SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.

With SWR, components will get a stream of data updates constantly and automatically. And the UI will be always fast and reactive.

Features

  • ๐ŸŽ‰ ย  Built for Svelte
  • ๐Ÿ”ฅ ย  Extremely small and well packed at 2KB.
  • ๐Ÿ”ฅ ย  No dependencies (one polyfill for EventTarget).
  • ๐Ÿ‘ ย  Built-in cache and request deduplication.
  • ๐Ÿ‘€ ย  Dependent fetching of data that depends on other.
  • ๐Ÿ‘€ ย  Real time experience.
  • โญ ย  Typescript friendly.
  • ๐Ÿ‘ ย  Error handling by using the error variable provided.
  • โšก ย  Efficient DOM updates using Svelte reactivity.
  • โšก ย  Efficient HTTP requests are only done when needed.
  • ๐Ÿ‘ ย  Manual revalidation of the data by using revalidate().
  • ๐Ÿ‘ ย  Optimistic UI / Manual mutation of the data by using mutate().
  • ๐Ÿ’ค ย  Window focus revalidation of the data.
  • ๐Ÿ’ค ย  Network change revalidation of the data.
  • ๐Ÿ‘ ย  Initial data support for initial or offline data.
  • ๐Ÿ‘ ย  Clear cache when you need to invalidate all data or the specified keys (eg. a user logout).
  • ๐Ÿ’ค ย  Offline support to be used without any revalidations with string keys.
  • ๐Ÿ‘ ย  Global configuration available or per hook call.

Installation

You can use npm or yarn to install it.

npm i sswr
yarn add sswr

Getting Started

<script>
  import { useSWR } from "sswr";
  // Call the `useSWR` and pass the key you want to use. It will be pased
  // to the fetcher function. The fetcher function can be configured globally
  // or passed as one of the options to this function.
  const { data: posts } = useSWR("https://jsonplaceholder.typicode.com/posts");
</script>

{#if $posts}
  {#each $posts as post (post.id)}
    <h1>{post.title}</h1>
    <p>{post.body}</p>
  {/each}
{/if}

This is a simple example that will use SWR as the strategy to fetch the data. In this particular case, all the default options are used (or the ones specified in the global config) and it will fetch the data using the default or global fetcher and update the DOM when the request is done.

Configuration options

All hook calls can have their respective configuration options applied to it. Nevertheless you can also configure global options to avoid passing them to each hook call.

Signature

function useSWR(key, options): SWRResponse
// Can be destructured to get the response as such:
const { data, error, mutate, revalidate } = useSWR(key, options)

Parameters

  • key: A resolved or non-resolved key. Can either be a string, or a function. A function can be used for dependent fetching as seen below.
  • options: An optional object with optional properties such as:
    • cache: SWRCache = new DefaultCache(): Determines the cache to use for SWR.
    • errors: EventTarget = new EventTarget(): Determines the error event target where the errors will be dispatched.
    • fetcher: (key) => Promise<any> = (url) => fetch(url).then((res) => res.json()): Determines the fetcher function to use. This will be called to get the data.
    • initialData: any = undefined: Represents the initial data to use instead of undefined. Keep in mind the component will still attempt to re-validate unless revalidateOnMount is set false.
    • revalidateOnStart: boolean = true: Determines if the hook should revalidate the key when it is called.
    • dedupingInterval: number = 2000: Determines the deduping interval. This interval represents the time SWR will avoid to perform a request if the last one was made before dedupingInterval ago.
    • revalidateOnFocus: boolean = true: Revalidates the data when the window re-gains focus.
    • focusThrottleInterval: number = 5000: Interval throttle for the focus event. This will ignore focus re-validation if it happened last time focusThrottleInterval ago.
    • revalidateOnReconnect: boolean = true: Revalidates the data when a network connect change is detected (basically the browser / app comes back online).

Return Values

  • data: Writable<D | undefined>: Stores the data of the HTTP response after the fetcher has proceesed it or undefined in case the HTTP request hasn't finished or there was an error.
  • error: Writable<E | undefined>: Determines error of the HTTP response in case it happened or undefined if there was no error or the HTTP request is not completed yet.
  • mutate: (value, options) => void: Mutate alias for the global mutate function without the need to append the key to it.
  • revalidate: (options) => void: Revalidation alias for the global revalidate function without the need to append the key to it.
  • clear: (options) => void: Clears the current key data from the cache.
  • isLoading: Readable<boolean>: Determines if the request is still on its way and therefore, it's still loading.
  • isValid: Readable<boolean>: Determines if the data is valid. This means that there is no error associated with the data. This exists because errors do not wipe the data value and can still be used.

Global configuration options

You can configure the options globally by creating a SWR instance and using it in your svelte application. This step is not mandatory but it's recommended for most apps.

You can either choose to manually create a SWR instance and import it when needed or replace the default SWR instance used by all exported APIs. The second is recommended if only one instance will be needed for your application.

Signature

function createSWR(options): VSWR
function createDefaultSWR(options): VSWR

Parameters

  • options: SWROptions: Parameters of the options that will be passed to all components. They are the same as the ones on each useSWR function call.

Return value

A SWR instance that can be used to access all the API.

Dependent fetching

<script>
  import { useSWR } from "sswr";

  const { data: post } = useSWR("https://jsonplaceholder.typicode.com/posts/1");
  // We need to pass a function as the key. Function will throw an error when post is undefined
  // but we catch that and wait till it re-validates into a valid key to populate the user variable.
  $: ({ data: user } = useSWR(
    () => `https://jsonplaceholder.typicode.com/users/${$post.userId}`
  ));
</script>

{#if $post}
  <div>{$post.title}</div>
{/if}
{#if $user}
  <div>{$user.name}</div>
{/if}

Re-validate on demand

Global revalidate function with given key

You can re-validate specific keys by importing the revalidate function.

import { revalidate } from 'sswr'

You can call this method anywhere in your application by giving it the key, and the options.

Signature

function revalidate(key, options): void
Parameters
  • key: Determines the key that is going to be re-validated. This must be a resolved key, meaning it must be a string or undefined. If undefined, the function will do nothing.
  • options: A partial object (meaning all props can be optional / undefined) that accepts the following options:
    • force: boolean = false:Determines if the re-validation should be forced. When a re-validation is forced, the dedupingInterval will be ignored and a fetch will be performed.

On specific hooks with keys

You can re-validate specific keys by grabing the revalidate function of the useSWR call. This function will allow you to perform a re-validation of the data on demand. There's no need to provide the key for this function since it's already bound to the hook key. It only accepts the options.

Signature

function revalidate(options): void
Parameters
  • options: Same as global revalidate (check above).

Example

<script>
  import { useSWR } from 'sswr'

  const { data: post, revalidate } = useSWR('https://jsonplaceholder.typicode.com/posts/1')
</script>

{#if $post}
  <div>{$post.title}</div>
  <button on:click={() => revalidate()}>Revalidate</button>
{/if}

Mutate on demand

Global mutate function with given key

You can mutate specific keys by importing the mutate function.

import { mutate } from 'sswr'

You can call this method anywhere in your application by giving it the key, the value and the options.

Signature

function mutate(key, value, options): void
Parameters
  • key: Determines the key that is going to be mutated. This must be a resolved key, meaning it must be a string or undefined. If undefined, the function will do nothing.

  • value: any | ((any) => any): Determines the new value to set. This can either be the value itself or a function that receives the current state and returns the new one.

  • options: A partial object (meaning all props can be optional / undefined) that accepts the following options:

    • revalidate: boolean = true: Determines if the mutation should attempt to revalidate the data afterwards.
    • revalidateOptions: Partial<SWRRevalidateOptions> = { ...defaultRevalidateOptions }: Determines the revalidation options passed to revalidate in case the parameter revalidate is set to true.

On specific hooks with keys

You can mutate specific keys by grabing the mutate function of the useSWR call. This function will allow you to perform a mutation of the data on demand. There's no need to provide the key for this function since it's already bound to the hook key. It only accepts the value and the options.

Signature

function mutate(value, options): void
Parameters
  • value: Same as global mutate (check above).
  • options: Same as global mutate (check above).

Example

Keep in mind we set revalidate to false to avoid it performing a HTTP request for this example, since this would just over-write the static data with the server data again.

<script>
  import { useSWR } from 'sswr'

  const { data: post, mutate } = useSWR('https://jsonplaceholder.typicode.com/posts/1')
</script>

{#if $post}
  <div>{$post.title}</div>
  <button on:click={() => mutate((state) => ({ ...state, title: 'Sample' }), { revalidate: false })}>
    Mutate only title
  </button>
  <button on:click={() => mutate({ title: 'Sample' }, { revalidate: false })}>
    Leave only title
  </button>
{/if}

Error handling

You can handle request errors by using the error return value on a hook call. This will return the specific error that happened to the hook. For example, a failed request.

Example

<script>
  import { useSWR } from 'sswr'

  const { data: posts, error } = useSWR('https://jsonplaceholder.typicode.com/posts')
</script>

{#if $error}
  <div>There was an error</div>
{:else if $posts}
 {#each $posts as post (post.id)}
    <h1>{post.title}</h1>
 {/each}
{/if}

Clear Cache

Global clear function with given keys

You can clear all the cached keys or the specified ones when you need to invalidate some keys.

To do this, you can use the clear global function.

import { clear } from 'sswr'

Signature

function clear(keys, options): void
Parameters
  • keys: A single key or a list with the keys to delete. If keys is undefined, all keys will be cleared from the cache.
  • options: A partial object containing one of the following options:
    • broadcast: boolean: Determines if the cache should broadcast the cache change to subscribed handlers. That means telling them the value now resolves to undefined.

On specific hooks with keys

You can clear specific keys by grabing the clear function of the useSWR call. This function will allow you to clear the data on demand. There's no need to provide the key for this function since it's already bound to the hook key. It only accepts the options.

Signature

function clear(options): void
Parameters
  • options: Same as global clear (check above).

Example

<script>
  import { useSWR } from 'sswr'

  const { data: post, clear } = useSWR('https://jsonplaceholder.typicode.com/posts/1')
</script>

{#if $post}
  <div>{$post.title}</div>
  <button on:click={() => clear()}>
    Clear cacheed data
  </button>
{/if}

Using with SvelteKit SSR

SvelteKit allows you to fetch data on the backend. This allows you to combine SSR (where your data is present in the HTML) with the live updating that this package provides.

Here is an example of how to implement the Getting Started example with support for SSR. In this example, we have disabled the revalidation on the client, althought it is also possible to re-hydrate the information on it if needed.

<script lang="ts" context="module">
  import type { Load } from '@sveltejs/kit';

  const url = 'https://jsonplaceholder.typicode.com/posts';

  export const load: Load = async ({ fetch }) => {
    const response = await fetch(url);

    return {
      props: {
        initialData: await response.json()
      }
    };
  };
</script>

<script lang="ts">
  import { useSWR } from 'sswr';

  interface Post {
    id: number;
    title: string;
    body: string;
  }

  export let initialData: Post[];

  const { data: posts } = useSWR<Post[]>(url, {
    initialData,
    revalidateOnStart: false
  });
</script>

{#if $posts}
  {#each $posts as post (post.id)}
    <h1>{post.title}</h1>
    <p>{post.body}</p>
  {/each}
{/if}

Contributors

sswr's People

Contributors

benbender avatar consoletvs avatar frederikhors avatar kevlened avatar khromov avatar lachlancollins avatar marekdedic avatar salisshuaibu11 avatar sammccord avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

sswr's Issues

revalidateOnMount missing?

๐Ÿ‘‹ I saw a reference to the revalidateOnMount configuration option in the README but I can't seem to find it in the code. Is it a feature that is planned for a future release?

It would be useful for me to set revalidateOnMount: false since I will be setting initialData from SvelteKit through SSR and don't want it to immediately refresh on the client.

Documentation typo: Global configuration options

You can configure the options globally by creating a SWR instance and using it in your Vue application. This step is not mandatory but it's recommended for most apps.

  1. Vue is used instead of Svelte

make revalidate() fires immediately?

hey first of all thanks for the awesome plugin.

when using revalidate(), it doesn't seem to refetch the data immediately, but I have to click out the window and click back again. is it possible to make it immediately fires when called?

Suggestion: rename useSWR to something else

Love the idea of swr in Svelte but it would be neat to keep it aligned with how and what things are called in Svelte.

I assume the use moniker is taken from the react ecosystem (hooks)? The use keyword has a meaning in Svelte and it will probably confuse users a bit. I suggest renaming useSWR to something else. Maybe just... swr()?

Is there a changelog?

Hi,
is there any changelog for SSWR? I recently tried updating to v2, but that is honestly quite hard to do without knowing what has caused the major version bump (I presume it's just svelte v4, but I have no idea...)

I tried looking in swrev, but there isn't one either...

`fetcher` is sometimes ignored and it uses the default `fetch`

I ran into a scenario where passing a custom fetcher to useSWR was still creating fetch calls.

I had to work around it as follows unfortunately:

  const swr = createSWR({ fetcher: readUser });
  const { data: user, revalidate } = swr.useSWR("usertest", {
    dedupingInterval: 0,
    revalidateOnFocus: false,
  });

I was noticing that if I passed fetcher to useSWR instead, I'd see XHR to /usertest even though my fetcher doesn't use XHR at all.

Support synchronous `fetcher` function

For local storage cases like localStorage, I ran into an obscure error where it was complaining that the return value didn't have .catch. I fixed by turning my sync fetcher into an async function.

Furthermore, it might be worth considering accepting the fetcher as the second param, since that's how SWR also works.

If `fetcher` returns `null` the revalidation is ignored

This was my fetcher function:

  async function readUser() {
    return localStorage.user ?? null;
  }

If I'd go to the console and run localStorage.removeItem('user'), revalidation of any kind (whether via calling revalidate or focus revalidation) wouldn't work, until I switched it to:

  async function readUser() {
    return localStorage.user ?? false;
  }

Add `isValidating` prop

In order to show whether the application data is loading, or if just something falsy got returned from the API, sswr should probably add a isValidating prop too.

What's the status?

Thanks for your work on this project.

Is it currently production-ready?

Is there any serious intention to maintain it in the future?

Difference to @tanstack/svelte-query

Maybe that's a stupid question. I was using svelte-query up until now, ...not sure which one was first, but is there any huge difference between the two?oO

Dependent fetching doesn't revalidate when changing to an already cached value

Hi, I'm using dependent fetching and after #33 it works for me - sort of.

I have a SWR table with a filtering function - user enters a value into the field and with dependent fetching, the value is used as part of a request. While the request is in-flight a show a spinning loading indicator.

Initially, this works great:

  1. User enters/changes a value
  2. The SWR changes to undefined, I show the loading indicator
  3. A request is triggered
  4. When the request resolves, the SWR changes from undefined to the actual value and the table is shown.

However, when the user enters a value that he has already previously entered (so the request response is in SWR's cache), the following happens:

  1. User enters/changes a value
  2. The SWR changes to undefined, I show the loading indicator
  3. Nothing more - no request is fired (I use a long dedupingInterval), no value is returned.

I think this might actually be an issue with swrev?

SvelteKit - Function called outside component initialization

Hi

I'm trying to use sswr with a newly created SvelteKit project, building with the node adapter.
I have added some simple test after having had issues:

	import { useSWR } from 'sswr';

	try {
		const { data } = useSWR('http://jsonplaceholder.typicode.com/posts/1');
	} catch(e) {
		console.log(e);
	}

test to a

  • route
  • component

and I always get back the same error:

Error: Function called outside component initialization
    at get_current_component (index.mjs:813)
    at onMount (index.mjs:820)
    at l.useSvelte (index.js:1)
    at useSWR (index.js:1)
    at instance ([dialogId].svelte:42)
    at init (index.mjs?v=99bae134:1660)
    at new U5BdialogIdu5D ([dialogId].svelte:153)
    at createComponent (svelte-hooks.js:136)
    at U5BdialogIdu5D.targetCmp.$replace (svelte-hooks.js:183)
    at refreshComponent (proxy.js:170)

Any idea why that might be?

SvelteKit - Named export 'SWR' not found

I use sswr in a SvelteKit application ("@sveltejs/kit": "^1.0.0-next.442").

In dev, everything works fine. However, when I run npm run build and npm run preview and load a page that imports sswr, I see the following error:

SyntaxError: Named export 'SWR' not found. The requested module 'swrev' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'swrev';
const { SWR } = pkg;

Does anyone have a working example of sswr with SvelteKit? Maybe @khromov because of #34 ๐Ÿค”?

Expose a method to get the cache?

In the classic example of list/detail if I click on the single detail element I wanna check the cache (under list key) to get data for initialData but now there is no way to get cache right?

Should we expose methods for get the cache?

Array as keys?

Now I'm using svelte-query but I'm not happy with it: it has not-so-convenient APIs (@benbender is working on it, but the maintainer is not so active, so I doubt it will change in a short time).

After the "fix" for Svelte Kit I'm trying sswr.

The first "issue" is about the query keys. Svelte-Query also allows you to use an array of keys for use cases such as pagination or filtering, you know... https://sveltequery.vercel.app/guides/query-keys.

What do you think about?

Is it so hard to add?

SSWR no longer updating with longer `dedupingInterval`

Hi, I recently tried updating SSWR from 1.10.0 to 2.1.0 and with the update, I encountered the following issue:

I have set a fairly large deduping interval. However, after the update, when I fetch some data with sswr, I first get the initial undefined, but I don't get the actual data when they are subsequently fetched. So I cannot use a larger deduping interval, because that basically means I don't actually get the data...

Dependent fetching just doesn't work?

If I clone the default Svelte template via npx degit sveltejs/template my-svelte-project, then yarn add sswr, and copy&paste the dependent fetching example from the README into "App.svelte"...

<script>
  import { useSWR } from "sswr";

  const { data: post } = useSWR("https://jsonplaceholder.typicode.com/posts/1");
  // We need to pass a function as the key. Function will throw an error when post is undefined
  // but we catch that and wait till it re-validates into a valid key to populate the user variable.
  $: ({ data: user } = useSWR(
    () => `https://jsonplaceholder.typicode.com/users/${$post.userId}`
  ));
</script>

{#if $post}
  <div>{$post.title}</div>
{/if}
{#if $user}
  <div>{$user.name}</div>
{/if}

Only the $post store ever gets populated - and what's more, the https://jsonplaceholder.typicode.com/users/${$post.userId} URL never seems to get fetched.

image

I was, actually tracking down a bug I thought was on my side - I'm changing the key based on a reactive variable (which in turn is set based on a useSWR fetch) and not a SWR-returned store directly (as in the example). So, I thought that the fact the second fetch never happens is a consequence of the way the reactivity is set up (since useSWR() uses onMounted(), I presume a useSWR() call which happens later (i.e. when my reactive variable is updated) doesn't get hooked properly) - but now I'm not so sure. This may be a separate issue entirely, in which case I will delete this portion of the issue.

Thanks in advance!

Svelte 4 support

This library has a version of Svelte 3 pinned in the package.json although Svelte 4 support should be straightforward. I can open a PR if this would be accepted

ref: vercel/ai#271

How does one declare the type of the incoming data?

When I write this:

<script>
  import { useSWR } from "sswr"

  const { data: posts } = useSWR("https://jsonplaceholder.typicode.com/posts")
</script>

<ul>
  {#each $posts as post}
    <li>{post.title}</li>
  {/each}
</ul>

Then typescript tells me that I can't use $posts in an {#each} block, because the type of $posts is unknown.

edit

Okay I figured it out, apparently I needed to write it like so:

<script>
  import Counter from "$components/Counter.svelte"
  import { createSWR } from "sswr"

  interface Post {
    id: number
    userId: number
    title: string
    body: string
  }

  const swr = createSWR<Post[]>()

  const { data: posts } = swr.useSWR("https://jsonplaceholder.typicode.com/posts")
</script>

<ul>
  {#each $posts as post}
    <li>{post.title}</li>
  {/each}
</ul>

But is there a good reason why this has to go through createSWR? Why can't I define a type directly on the useSWR() function? Like const { data: posts } = useSWR<Post[]>("https://jsonplaceholder.typicode.com/posts") ?

Do we really need `isValid`?

From vswr code:

// Determines if the data is valid. This means that
// there is no error associated with the data.
// This exists because errors do not wipe the data value
// and can still be used.
const isValid = computed(() => data.value !== undefined && error.value === undefined)

Do we really need this?

@benbender.

`data` is `undefined` using reactive query

Using the below code it makes data === undefined. Why?

REPL: https://svelte.dev/repl/40782b4783244075b8c58cffbcf9acd4?version=3.42.1.

<script lang="ts">
  import { useSWR } from "sswr";

  let pagination = defaultPagination;

  $: ({ data, error } = useSWR(`players`, {
    fetcher: () => Promise.resolve(service.playerList({ pagination })),
  }));

  $: console.log("$error:", $error);
  $: console.log("$data:", $data); // $data === undefined as soon as I click Next page button

  function nextPage() {
    pagination = { ...pagination, page: $data.pageInfo.currentPage + 1 };
  }
</script>

<button on:click={nextPage}>Next page</button>

{#if $error} {$error.message} {:else if !$data} Loading... {:else}
<ul>
  {#each $data.players as player (player.id)}
  <li>
    <a href="/players/{player.id}">{player.id}</a>
  </li>
  {:else}
  <h1>No players</h1>
  {/each}
</ul>
{/if}

Quality control & maintenance of SSWR

Let me start by saying thank you for creating SSWR, I know it's open source and you probably created it for free in your spare time, I'm very thankful for that. I also love the library, its ergonomics and pretty great docs. So thank you for that.

With that being sad, I feel like I encounter a lot of subtle issues every time I work with SSWR. Because doing SWR and async requests in general is quite tricky in my opinion, it's very difficult for me as a user to use SSWR when every time something doesn't work as I expected, I don't know if it is my issue, or if SSWR has a bug. To illustrate, in the ~year I have benn working with SSWR, I have encountered #24, #41, #42, #43 and #50.

So, what do we do about this? I propose starting with #51 and adding a test suite. Having a set of tests that reflect the expected behaviour and past issues can catch a lot of regressions, such as #50. I am willing to submit a PR adding some tests - with that in place, it would be easier to fix current issues and catch future ones.

Is that something you are ok with and willing to maintain going forward? I love this library, but honestly, I want something that works. There are some alternatives (tanstack query, svelte query, @svelte-drama/swr and possibly others), but if you plan on maintaining sswr into the future, I'd rather contribute here than switch to a lib I don't really like. On the other hand, I think it is fair game to say that your needs and interests have changed and you are no longer interested in maintaining SSWR - in that case, maybe somebody else will step up (I know it won't be me), or alternatively, the best thing would be to archive SSWR and point people to an alternative. But I don't know if that's the case - you seem to publish new versions quite frequently, yet at the same time some long standing issues like #24 remain unsolved...

None of this is meant in a bad way, I like the library, want it to succeed, I'm willing to contribute to that, but I'd like to know where it stands. Thanks!

Global Background Fetching Indicator

PROLOGUE

I'm sorry if I'm always mentioning svelte-query these days.

I'll stop shortly (I'm starting a new project and I wanna use your gorgeous sswr).

I hope to be a great tester/helper/improver.

REQUEST

Svelte-Query has a Global Background Fetching Indicator.

I can use it in my __layout.svelte file like this:

<script>
  import { useIsFetching } from "@sveltestack/svelte-query";

  const isFetching = useIsFetching();
</script>

{#if $isFetching}
  <div>Queries are fetching in the background...</div>
{/if}

Can we do the same?

It's really really useful!

Posible vite4 incompatibility

Hello and thank you for your time,

I got this weird error on a fresh sveltekit installation, just by pasting the example code in a +page.svelte

Internal server error: Cannot read properties of undefined (reading 'SWR')
      at eval (/node_modules/sswr/dist/sswr.es.js:130:35)
      at async instantiateModule (file:///Users/vlad/Documents/zecode/@lib/JS/vicon/frontend/node_modules/vite/dist/node/chunks/dep-ca21228b.js:52420:9) (x2)
TypeError: Cannot read properties of undefined (reading 'SWR')
    at eval (/node_modules/sswr/dist/sswr.es.js:130:35)
    at async instantiateModule (file:///Users/vlad/Documents/zecode/@lib/JS/vicon/frontend/node_modules/vite/dist/node/chunks/dep-ca21228b.js:52420:9)

My package.json is:

{
	"name": "vbox",
	"version": "0.0.1",
	"scripts": {
		"dev": "vite dev",
		"build": "vite build",
		"preview": "vite preview",
		"test": "playwright test",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
		"test:unit": "vitest"
	},
	"devDependencies": {
		"@fontsource/fira-mono": "^4.5.10",
		"@neoconfetti/svelte": "^1.0.0",
		"@originjs/vite-plugin-commonjs": "^1.0.3",
		"@playwright/test": "^1.28.1",
		"@sveltejs/adapter-auto": "^1.0.0-next.90",
		"@sveltejs/kit": "^1.0.0-next.587",
		"@types/cookie": "^0.5.1",
		"autoprefixer": "^10.4.13",
		"postcss": "^8.4.21",
		"svelte": "^3.54.0",
		"svelte-check": "^2.9.2",
		"tailwindcss": "^3.2.7",
		"tslib": "^2.4.1",
		"typescript": "^4.9.3",
		"vite": "^4.0.0",
		"vitest": "^0.25.3"
	},
	"type": "module",
	"dependencies": {
		"@auth/core": "^0.5.0",
		"@auth/sveltekit": "^0.2.2",
		"@popperjs/core": "^2.11.6",
		"@tailwindcss/forms": "^0.5.3",
		"@tailwindcss/typography": "^0.5.9",
		"chart.js": "^4.2.1",
		"daisyui": "^2.51.2",
		"sswr": "^1.7.0"
	},
	"license": "MIT"
}

I'm on a M1 mac.
I ended up whit this setup without specifically wanting to use vite 4. If there is a bare-bones sswr project somewhere I can clone, it would be great, as I am in an early stage of development and there is no significant effort loss.
Thanks again

Server side rendering SvelteKit example does not work

The current SSR example from the readme does not work. I have submitted a working SSR example in #32 and I think that is the only way to have working SSR. ("Working" in this case means the rendered data is present in the HTML response from the server.)

Demo

You can see that "undefined" flashes on the screen before the data loads:
Animation

Repro (code from readme)

<script lang="ts" context="module">
  import type { Load } from '@sveltejs/kit';

  const url = 'https://jsonplaceholder.typicode.com/posts';

  export const load: Load = async ({ fetch }) => {
    const response = await fetch(url);

    return {
      props: {
        initialData: await response.json()
      }
    };
  };
</script>

<script lang="ts">
  import { useSWR } from 'sswr';

  interface Post {
    id: number;
    title: string;
    body: string;
  }

  export let initialData: Post[];

  const { data: posts } = useSWR<Post[]>(url, {
    initialData,
    revalidateOnStart: false
  });
</script>

<pre>{JSON.stringify($posts)}</pre>

Misc

I have also tried an alternative approach with data fetching through a Page Endpoint but that has the same problem where the value is undefined at the start.

Multiple SWRs in one component keep resetting each other

Hi,
I have a component with the following setup:

<script lang="ts" strictEvents>
  import { useSWR } from "sswr";

  const { data: rawCompetences } = useSWR("example.com/competence");
  const { data: rawLessons } = useSWR("example.com/lesson");
  const { data: rawFields } = useSWR("example.com/field");

  rawCompetences.subscribe(value => {
    console.log("COMPETENCES");
    console.log(value);
  });
  rawLessons.subscribe(value => {
    console.log("LESSONS");
    console.log(value);
  });
  rawFields.subscribe(value => {
    console.log("FIELDS");
    console.log(value);
  });
  $: console.log("CONDITION") ||
    console.log(
      !(
        $rawCompetences === undefined ||
        $rawLessons === undefined ||
        $rawFields === undefined
      )
    );
</script>

And I see in the console that basically, the first SWR gets loaded, on completion, it marks the component as dirty, which resets the other 2 SWRs to undefined. Then the second SWR loads and does the same to the third. Only once the third gets loaded that the "CONDITION" resolves to true (it briefly resolves to true each time one of the SWR resolves but then that immediately resets the whole component...)

Mind you, all 3 of the SWRs were loaded before, so I would expect the component to be ready (all three != undefined) immediately with the stale values and update later. Instead, the component is ready only once all 3 SWRs revalidate.

Am I doing something wrong? I looked at revalidateOnStart, but i do want to revalidate, I just want it to also use the stale value while doing that....

Issue during SSR, fetch not defined

This issue happens in SvelteKit and I presume also in Sapper.

This issue could relatively easily be mitigated if createSWR() wasn't automatically called. Then a developer like me could choose not to call it during SSR, or to call it with a special fetcher.

[HELP] Error: Function called outside component initialization

Hi!
Thank you for creating SSWR!

I'm getting Error: Function called outside component initialization but i can't understand why.
SSWR is called inside onMount.
onMount -> wrapper method -> SSWR.

Error trace:
image

Where it starts:
image

Wrapper method:
image

Versions:

"svelte": "^3.49.0",
"svelte-preprocess": "^4.10.6",
"vite": "^3.0.2",
"sswr": "^1.7.0",
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.44",

I don't use SvelteKit

What i'm missing out? What i'm doing wrong? Cant SSWR be used inside promises?

Edit:
I've tried upgrading "@sveltejs/vite-plugin-svelte": "^1.1.0", but didnt make any change.

Cannot use `() => string` as key?

Using this line:

$: ({ data, error } = useSWR(() => `${playerList}`, {...

Typescript throws with:

Argument of type '() => string' is not assignable to parameter of type 'string'.ts(2345).

Am I wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.