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

[Bug] query invalidation and a simultaneous cache key change lead to inconsistent state #154

Open
tobiasdcl opened this issue Jan 7, 2025 · 1 comment
Labels
🐞 bug this isn't working as expected

Comments

@tobiasdcl
Copy link

Hey there,
first of all awesome work - thank you! ❤️

We recently migrated from @tanstack/vue-query to @pinia/colada. Initially everything looked great but we got some strange errors that were initially hard to reproduce.
After a long time I was able to track down the issue, which originates from a query invalidation and a simultaneous cache key change that leads to the data beeing briefly undefined despite using placeholderData
I tried to understand why this was happening to submit a PR but was unable to fully grasp the root cause.

I put together a minimal reproduction sample with some comments.
Execution environment was a nuxt application (probably not relevant, just wanted to mention it) - "@pinia/colada": "0.13.2"

<template>
  <div>
    <button type="button" @click="clickHandler">Click me</button>
    <br />
    queryKey: {{ queryKey }}
    <br />
    data: {{ data }}
  </div>
</template>

<script setup lang="ts">
const queryKey = ref(1);

const queryCache = useQueryCache();

/**
 * `data` should always be defined and is either `{ description: 'query result' }` or `{ description: 'placeholder' }`
 */
const { data } = useQuery({
  key: computed(() => ['common', queryKey.value]),
  query: async () => {
    return Promise.resolve({ description: 'query result' });
  },
  placeholderData: { description: 'placeholder' },
});

function clickHandler() {
  console.log('clickHandler invoked');

  /**
   * The issue only happens when you change the cache key and invalidate the key at the same time.
   * Performing only one of the two actions will not trigger the issue.
   */
  queryKey.value++;
  queryCache.invalidateQueries({
    key: ['common'],
  });

  /**
   * In order to trigger the bug you need to access the prop immediately after the cache invalidation.
   * In our application this happened through a computed property that was used during the fetch of a secondary query but I was able to simplify it to this
   *
   * `data.value.description` should always be safe to access since we are using a `placeholder` value - but it is not
   *
   * 💥 BOOM 💥
   * TypeError: Cannot read properties of undefined (reading 'description'
   */
  console.log('[post invalidation] data', data.value.description);
}

onMounted(() => {
  console.log('[onMounted] data', data.value);
});
</script>

console output:

[onMounted] data {description: 'placeholder'}

<button click>

clickHandler invoked
runtime-core.esm-bundler.js:268 Uncaught TypeError: Cannot read properties of undefined (reading 'description')
    at clickHandler (repro.vue:48:54)
    at callWithErrorHandling (runtime-core.esm-bundler.js:199:19)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:206:17)
    at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js:729:5)
@github-project-automation github-project-automation bot moved this to 🆕 Triaging in Pinia Colada Roadmap Jan 7, 2025
@posva posva added the 🐞 bug this isn't working as expected label Jan 10, 2025
@posva
Copy link
Owner

posva commented Jan 10, 2025

Thank you! This is very helpful. The placeholderData should be triggered early

@posva posva moved this from 🆕 Triaging to Todo in Pinia Colada Roadmap Jan 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 bug this isn't working as expected
Projects
Status: Todo
Development

No branches or pull requests

2 participants