sswr icon indicating copy to clipboard operation
sswr copied to clipboard

`data` is `undefined` using reactive query

Open frederikhors opened this issue 4 years ago • 8 comments

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}

frederikhors avatar Aug 11 '21 14:08 frederikhors

Can I know more about what service.playerList does under the hood?

ConsoleTVs avatar Aug 12 '21 00:08 ConsoleTVs

Can I know more about what service.playerList does under the hood?

In the REPL for this issue I used a simple fetch with the same issue: https://svelte.dev/repl/40782b4783244075b8c58cffbcf9acd4?version=3.42.1.

My service is similar.

frederikhors avatar Aug 12 '21 07:08 frederikhors

THIS IS HUGE and prevent me from using sswr today.

frederikhors avatar Aug 12 '21 09:08 frederikhors

I'm going to explore this after work. Thanks for the report.

ConsoleTVs avatar Aug 12 '21 13:08 ConsoleTVs

Having the same issue here with trying to get pagination to work.

Given the following code in a svelte component:

  /** Item position to start at */
  let offset = 0
  /** Number of items to get */
  let first = 10

  $: ({ data: pageData } = useSWR(() => 'pageItems', {
    fetcher: () => query('someItemList', { first, offset })
  }))

  $: console.log('page data', $pageData)

pageData is initially populated with data however when I update offset via a button press (offset += first), pageData becomes undefined and then no longer updates either on further changes to offset.

The same behaviour happens when not using a custom fetcher:

{...}
  $: ({ data: pageData } = useSWR(() => `api/someItemList?first=${first}&offset=${offset}`))
{...}

Terrahop avatar Aug 26 '21 16:08 Terrahop

@Terrahop You are simply rerunning useSWR reactivly with different parameters. Therefor data is initialized as undefined at the beginning of the new request as per docs. See:

data: Writable<D | undefined>: Stores the data of the HTTP response after the fetcher has processed it or undefined in case the HTTP request hasn't finished or there was an error.

So imho this is expected behaviour.

The solution to this is either:

  • save the old data in an intermediate variable until new data arrives (outside of useSWR())
  • extend the api of useSWR with something like keepData: boolean.

benbender avatar Sep 04 '21 09:09 benbender

Ah got it thanks for clearing that up, I'll take a look at extending useSWR then.

Terrahop avatar Sep 10 '21 12:09 Terrahop

I'm facing this issue as well, which is preventing me from using useSWR, unfortunately.

akiarostami avatar Nov 03 '21 21:11 akiarostami