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

Rerender just an item in list, not all the list items. #19

Closed
frederikhors opened this issue Jun 5, 2019 · 8 comments · Fixed by #52
Closed

Rerender just an item in list, not all the list items. #19

frederikhors opened this issue Jun 5, 2019 · 8 comments · Fixed by #52

Comments

@frederikhors
Copy link
Contributor

frederikhors commented Jun 5, 2019

I have a big list of items.

Everything works good. But.

Everytime I update an item the big list re-render itself.

REPRODUCTION:


Maybe this is related to this example in Svelte tutorial https://svelte.dev/tutorial/svelte-options?

Have you already had this problem? @timhall @jacwright @lukeed

@sergelerner
Copy link

@frederikhors I'm trying to understand the same thing. Wondering if you learned anything since?

@lukeed
Copy link

lukeed commented Dec 31, 2019

Sorry, no experience here. Don't use Apollo/GraphQL at all

@frederikhors
Copy link
Contributor Author

@sergelerner not much. Can you answer today?

@Momics
Copy link

Momics commented Jan 22, 2020

I just had a similar issue. I figured it is because of the #await block. Just before updating the store the promise is 'reset'. This results in the entire each loop being rerendered. I am not sure if this is intended behaviour.

I fixed it by awaiting the promise in between the script tags like so:

<script>
  import { getClient, query } from "svelte-apollo";

  const client = getClient();
  const data = query(client, {
    query: SOME_QUERY,
  });

  let resultData = []
  $: $data.then(data => resultData = data.data.queryResult)
  
</script>

{#each resultData as d (d._id)}
  <div>{d}</div>>
{/each}

I don't think this is an elegant solution, but it works for me.

@frederikhors
Copy link
Contributor Author

@timhall Is this something we can fix?

@cdock1029
Copy link

If you add this in Button.svelte

onDestroy(() => {
  console.log("destroyed", player.id);
});

or this in App.svelte

{#await $players}
{console.log('LOADING..')}
  Loading players...
{:then result}

it does seem to show that {:then } block is unmounted and remounted whenever data is changed as @Momics explained.

I had similar issue when having a list of items that depended on an id variable that would change, it would flash the whole list component as it was destroyed.

I made this component to address this issue:

<!-- Loader.svelte -->
<script>
  import { query as apolloQuery } from 'svelte-apollo'
  import { client } from '../utils/apollo'

  export let query
  export let variables = undefined
  export let initial = null

  let data = initial

  $: q = apolloQuery(client, { query, variables })

  $: (async () => {
    let result = await $q
    setData(result.data)
  })()

  function setData(d) {
    data = d
  }
</script>

{#await $q}
  <slot {data} loading={true} />
{:then q}
  <slot {data} loading={false} />
{/await}

Used in this way:

 {#if $propertyId}
    <Loader
      let:data
      let:loading
      query={DASHBOARD}
      variables={{
        propertyId: Number($propertyId),
        limit,
        offset: limit * page,
        filter: $filter$ ? `%${$filter$}%` : null }}>
      {#if data}
        <table>
          ....
       
          <!-- Pagination updates data in way not shown here, but notice "loading"
          used here sort of like a simplistic useTransition(..) from React to show 
           intermediate loading state next to pagination buttons before data items update  -->
           <Pagination
              colspan={cols}
              count={data.units_aggregate.aggregate.count}
              {loading}
              bind:limit
              bind:page
              on:prev={() => (expandedRow = null)}
              on:next={() => (expandedRow = null)} /> 
        </table>

@frederikhors
Copy link
Contributor Author

frederikhors commented Apr 23, 2020

#43

@peacememories
Copy link

This can be worked around by using a derived state like so:

 const results = derived(
    standardsQuery,
    async ($query, set) => set(await $query),
    cache.data
  );

This version does not use {#await} at all, but interestingly, {#await} can handle non-promise values. So what could be changed is that svelte-apollo emits a promise when the query is created, and then emits raw values whenever a result is already available. this way, the waiting portion of {#await} would only be hit when there is actual waiting going on

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.

6 participants