vuejs / pinia

🍍 Intuitive, type safe, light and flexible Store for Vue using the composition api with DevTools support
https://pinia.vuejs.org
MIT License
13.11k stars 1.05k forks source link

docs: Added alternative way of defining the state with reactive instead of ref #2503

Closed JasonLandbridge closed 11 months ago

JasonLandbridge commented 11 months ago

Hi,

A method I've been using for a long time when setting up my Pinia stores is to use reactive instead of refs which has a few advantages:

I've added this method to the documentation. I have used this method extensively without any downsides in my projects and it seems to be an improvement over the current recommended store setup.

netlify[bot] commented 11 months ago

Deploy Preview for pinia-playground canceled.

Name Link
Latest commit b49be07b28f4fe2d9953f4c04f05386852db9cec
Latest deploy log https://app.netlify.com/sites/pinia-playground/deploys/655f1c917bf8fb0008056953
netlify[bot] commented 11 months ago

Deploy Preview for pinia-official ready!

Name Link
Latest commit b49be07b28f4fe2d9953f4c04f05386852db9cec
Latest deploy log https://app.netlify.com/sites/pinia-official/deploys/655f1c9189bb540008d474ad
Deploy Preview https://deploy-preview-2503--pinia-official.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

posva commented 11 months ago

Thanks! This does have some downsides, like putting every piece of state together. I fear people will not think of splitting up into multiple state objects and creating huge stores, creating a maintenance burden. Because of this, I prefer not to add it to docs.

JasonLandbridge commented 11 months ago

@posva, closing it was a bit harsh. I see the concern of not splitting it up but the code provided was just a simple example. This could easily be multiple reactive state objects where refs are grouped together:

export const useCounterStore = defineStore('counter', () => {
  const state1 = reactive({
    count: 0,
    name: 'Eduardo',
  })

  const state2 = reactive({
    count: 0,
    name: 'Eduardo',
  })

  const state3 = reactive({
    count: 0,
    name: 'Eduardo',
  })

  const doubleCount = computed(() => state.count * 2)

  function increment() {
    state.count++
  }

  return {
    ...toRefs(state1),
    ...toRefs(state2),
    ...toRefs(state3),
    doubleCount,
    increment,
  };
})

Or are you against the principle of using reactive as state in pinia stores?

JasonLandbridge commented 11 months ago

@posva

I fear people will not think of splitting up into multiple state objects and creating huge stores, creating a maintenance burden.

This should belong in a best practices section then, right?

posva commented 11 months ago

@posva, closing it was a bit harsh

This is nothing personal: it helps me organize my work. The discussion is open 🙂

I don't think we have a section for best practices. It doesn't necessarily belong there, it really depends on how it is written. I do talk about this in my course https://masteringpinia.com, so maybe I should adapt some bits and put them in the docs too. The main issue about what you initially wanted to add is that the line between maintainable and lead-to-problems is very thin and requires explaining many other concepts

JasonLandbridge commented 11 months ago

@posva, I understand, no offense taken!

I agree in the sense that we want to steer away users from bad practices. I do see your argument as with reactive you have to use an object that can grow larger and larger instead of using separate refs. In practice, at for example my current employer, I keep seeing something like this:

import { Ref, ref } from 'vue';

export const state: Ref<{
    list: PaymentMethod[];
    loaded: boolean;
}> = ref({
    list: [],
    loaded: false,
});

Where objects as state are placed inside of a ref, leading to a lot of .value use any time the state is referenced. It might be debatable whether this is good practice, but I use this as an example how the usage of ref or reactive can both lead to the same issue of larger states.

This is why I'm seeing the use of reactive as a better alternative to the use of ref, although it does force the user to use an object as state.

Looking at this example here: #Setup-Stores

I see indeed separate state properties defined as refs, but in the #Option-Stores the state is again defined as an object which is essentially the same as using reactive but in a Composition API kind of way.

I'm split on the issue now, it could be a good alternative but it does need some extra information to make the user aware of the possible pitfalls.