Giter VIP home page Giter VIP logo

pinia-colada's Introduction

Pinia Colada logo


npm package build status


Pinia Colada (WIP)

The missing data fetching library for Pinia

This is a more complete and production-ready (not yet!) version of the exercises from Mastering Pinia.

Mastering Pinia banner

Warning

Pinia Colada is still experimental and not ready for production. New versions might introduce breaking changes. Feedback regarding new and existing options and features is welcome!

Pinia Colada is an opinionated yet flexible data fetching layer on top of Pinia. It features

  • ⚡️ Automatic caching: Smart client-side caching with request deduplication
  • 🗄️ Async State: Handle any async state
  • 📚 Typescript Support: Fully typed with Typescript
  • 💨 Bundle Size: Small bundle size (<2kb) and fully tree-shakeable
  • 📦 Zero Dependencies: No dependencies other than Pinia
  • ⚙️ SSR: Server-side rendering support

Installation

npm install pinia @pinia/colada

Install the plugins for the features you need:

import { createPinia } from 'pinia'
import { QueryPlugin } from '@pinia/colada'

app.use(createPinia())
// install after pinia
app.use(QueryPlugin, {
  // optional options
})

Usage

<script lang="ts" setup>
import { useRoute } from 'vue-router'
import { useMutation, useQuery } from '@pinia/colada'
import { updateContact as _updateContact, getContactById } from '~/api/contacts'

const route = useRoute()

const { data: contact, isFetching } = useQuery({
  // recognizes this query as ['contacts', id]
  key: () => ['contacts', route.params.id],
  query: () => getContactById(route.params.id),
})

const { mutate: updateContact } = useMutation({
  // automatically invalidates the cache for ['contacts'] and ['contacts', id]
  keys: ({ id }) => [['contacts'], ['contacts', id]],
  mutation: _updateContact,
})
</script>

<template>
  <section>
    <ContactCard
      :key="contact.id"
      :contact="contact"
      :is-updating="isFetching"
      @update:contact="updateContact"
    />
  </section>
</template>

License

MIT

pinia-colada's People

Contributors

elisepatrikainen avatar posva avatar renovate[bot] 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  avatar  avatar  avatar

pinia-colada's Issues

Investigate the `retry` option

  • Find real-case scenarios where this is used to evaluate how important this feature is
  • Ideally should be tree shakable (a plugin)

Gc timeout is not triggered in the context of a query declared with the `defineQuery` composable

It seems that the removeDep function is not called in the context of a query declared with the defineQuery composable. More precisely, the onScopeDispose hook seems not to be called.

Not sure if it is relevant, but I noticed that the scopes are not the same for a query declared with the useQuery composable and the defineQuery composable.

In the useQuery context:

Capture d’écran 2024-04-21 à 19 15 21

And in the defineQuery context:

Capture d’écran 2024-04-21 à 18 56 10

Note: I will provide later the demo of these two cases.

Docs

  • Quick Start
    • Installation
    • Introduction
    • Playsink
  • Guides
    • Queries
    • Query keys
    • Cache and refreshing data
    • Mutations
    • Optimistic updates
      • UI
      • Cache
  • Plugins
  • Cookbook

Preload queries

Allowing a query to be preloaded
Requires all the options rather than just the key as otherwise it might not exist

Introducing focus manager and online manager

Currently, every time useQuery is called, it registers callbacks for the visibilitychange and online events (if options.refetchOnWindowFocus or options.refetchOnReconnect are set to true).

Could we consider the introduction of a focus manager and online manager mechanism? This approach would allow us to manage subscriptions to changes in focus and online status uniformly, rather than registering new events each time.

A way to avoid using outside state

maybe a defineQuery(() => {}) to allow using globals and creating global state associated with the query (e.g. a page?).

Currently one can try to do this:

<script setup lang="ts">
const page = ref(1)
useQuery({
  query() {
     return fetchData(page.value)
  },
  key: () => ['key', page.value]
})
<script>

But this can fail in some scenarios, notably if the same key is used in a different component or if this gets abstracted with

export const useSomeData = () => {
const page = ref(1)
return useQuery({
  query() {
     return fetchData(page.value)
  },
  key: () => ['key', page.value]
})
}

and used in multiple components, the page will end up scoped to the first component that calls it. Both components will create a page ref but only the first one will be used within query and key. Therefore, if the first component is unmounted while the other still lives, the page ref will not be reactive anymore, breaking the usage.

Notes

  • An eslint plugin could warn agains this usage. It would be better to have some runtime warning but not sure how to do it, maybe checking for the active scope and saving it somewhere in dev only?
  • Maybe run within a computed and check its deps
  • The function version is nice to setup initial state. Each query/mutation is effectively a mini store

Design plugin architecture

  • Allow passing new options + types
  • hook into setup()
  • Move features to plugins
    • refetch on mount?
    • Invalidate keys

Q: vue-apollo Apollo Cache

So, when fetching with the apollo client all the fetched data lands in the normalized cache of apollo. Would there be any benefit in using pinia-colada or pinia in general to do the fetching other that maybe global availability, which would not be in issue since requests are cached anyway.

Refactor types to use a union for better type narrowing

TS now supports type narrowing when destructuring. So it's worth having multiple types for the return values of useQuery and useMutation

import { Ref, ShallowRef, ref, shallowRef } from "vue";

interface UseStuffReturnOn<T> {
  state: Ref<'on'>
  data: ShallowRef<T>
}

interface UseStuffReturnOff<T> {
  state: Ref<'off'>
  data: ShallowRef<T | undefined>
}

type UseStuffReturn<T> = UseStuffReturnOff<T> | UseStuffReturnOn<T>

export function useStuff<T>(initial: T): UseStuffReturn<T> {
  return {
    state: ref('on'),
    data: shallowRef(initial)
  }
}

const { data, state } = useStuff(0)

if (state.value === 'on') {
  data.value.toFixed()
}

add `useQueryState()`

Allows retrieving the query state by key

  • Should allow passing multiple keys to to match multiple queries and return the aggregated state of these queries
  • How should they combine data, error, and status? Should each have an individual array, an object, a map?
  • If the state doesn't exist, create it?
  • It should handle a reactive version of the matched keys

Same questions for useMutationState()

Mutation Store

Create a mutation store to hold the share state of mutation

MutationPlugin

Add a mutation plugin that allows setting up global options (onSuccess, etc that run after local ones)

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.