Skip to content
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

Passing inputs to createServerQuery on the client-side #34

Closed
smaven opened this issue Apr 26, 2024 · 6 comments · Fixed by #37
Closed

Passing inputs to createServerQuery on the client-side #34

smaven opened this issue Apr 26, 2024 · 6 comments · Fixed by #37

Comments

@smaven
Copy link
Contributor

smaven commented Apr 26, 2024

Let's say I'm using createServerQuery to prefetch a list of users on the server and pass the query to the client:

// +page.ts
import type { PageLoad } from './$types';
import { trpc } from '$lib/trpc/client';

export const load: PageLoad = async (event) => {
  const { queryClient } = await event.parent();
  const client = trpc(event, queryClient);

  return {
    users: await client.user.all.createServerQuery(),
  };
};

I can use the query result to display content accordingly:

<!-- +page.svelte -->
<script lang="ts">
  import type { PageData } from './$types';

  export let data: PageData;

  const users = data.users();
</script>

<h1>List of users</h1>

{#if $users.isFetching}
  <p>Loading...</p>
{:else if $users.error}
  <p>Error: {$users.error.message}</p>
{:else if $users.isSuccess}
  <ul>
    {#each $users.data as user}
      <li>{user.name}</li>
    {/each}
  </ul>
{:else}
  <p>No users found</p>
{/if}

Now I want to filter the list of users as someone types in an input field. This requires me to send an input to the query. My guess was I would be able to pass the input to data.users() just like I can pass the input to trpc($page).user.all.createQuery(input) but this does not work and I could not find an example to achieve this.

<!-- +page.svelte -->
<script lang="ts">
  import type { PageData } from './$types';

  export let data: PageData;

  let filter = '';

  $: users = data.users({ name: filter });
</script>

<input type="text" bind:value={filter} placeholder="Filter users" />

...

I might be missing something really obvious here as this seems to me like a very common use case: fetching data on the server, passing it to the client so that the client doesn't have to load it again when it hydrates and then the subsequent loading of data happens on the client when inputs vary depending on user actions.

Apologies if this has been already answered somewhere, I dug into the README and issues but couldn't find anything.

@smaven smaven changed the title Passing inputs to createServerQuery on the client-side Passing inputs to createServerQuery on the client-side Apr 26, 2024
@smaven smaven changed the title Passing inputs to createServerQuery on the client-side Passing inputs to createServerQuery on the client-side Apr 26, 2024
@vishalbalaji
Copy link
Owner

vishalbalaji commented Apr 29, 2024

@smaven Great catch! This is something I realized about a month ago, but I have been a bit busy with work lately and haven't been able to work on this lib all that much. Expect this to be fixed in the update.

@vishalbalaji
Copy link
Owner

Hi @smaven, thank you for opening this issue! This feature has been pushed and is available from v2.3.0 onward.

@smaven
Copy link
Contributor Author

smaven commented May 14, 2024

@vishalbalaji, I tried out the feature and I feel one thing is missing in the implementation. Currently, the query only re-runs if the input changes to a truthy value. I think the query should re-run whenever the input changes, no matter what its value is. Consider the following:

<!-- +page.svelte -->
<script lang="ts">
  import type { PageData } from './$types';

  export let data: PageData;

  let filter: string | null = 'foo';
  let switch = true;
  
  // input is `undefined` when no filter has been set. Query should still re-run.
  $: users = data.users(filter ? { name: filter } : undefined);
  
  // input is changed to `false`. Query should still re-run.
  $: status = data.status(switch)
</script>

<input type="text" bind:value={filter} placeholder="Filter users" />
<input type="checkbox" bind:checked={switch} />
...

The assumption is that the tRPC procedures can be configured to run with any input and the query should always re-run whenever the input changes even if the value is falsy.

Thanks for implementing this feature BTW! 🙌

vishalbalaji added a commit that referenced this issue May 14, 2024
vishalbalaji added a commit that referenced this issue May 14, 2024
* fix: handle for falsy client-side inputs

[Comment from #34 for reference](#34 (comment))

* bump version
@vishalbalaji
Copy link
Owner

vishalbalaji commented May 14, 2024

@smaven Thanks for pointing this out! Fix has been pushed in v2.3.1.

@smaven
Copy link
Contributor Author

smaven commented May 15, 2024

@vishalbalaji I've noticed another issue:

  1. Consider a page loads that has the query created by createServerQuery and its inputs change.
  2. A network request is made when the inputs change.
  3. If the inputs change back to any of the previously set inputs, the query will not make a network request and instead fetches the results from cache.

Expected behaviour: The query should respect the stale time and make a network request if data is stale.

It works fine if I do a client-side navigation to a different page and then back to the page with the query. But does not work when the page first loads.

@vishalbalaji
Copy link
Owner

vishalbalaji commented May 31, 2024

Hey @smaven, sorry for the late reply, have been a bit busy this past week.

I looked into this issue and its mainly happening because I am disabling refetchOnMount by default for the server query functions to prevent them re-running on the client.

So for now, if you are using staleTime, make sure to also set refetchOnMount to true for that query.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants