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

Setup store - A more comprehensive example #978

Closed
jenstornell opened this issue Jan 21, 2022 · 9 comments
Closed

Setup store - A more comprehensive example #978

jenstornell opened this issue Jan 21, 2022 · 9 comments

Comments

@jenstornell
Copy link

I think that the setup way of building a store will be the future. I would love to shift towards that in the docs.

Currently in the docs

https://pinia.vuejs.org/introduction.html#basic-example

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }

  return { count, increment }
})

Comprehensive example

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useStoreCounter = defineStore('counter', () => {
  // STATES
  const count = ref(0)

  // GETTERS
  const isEven = computed(() => {
    return count.value % 2 === 0
  })

  const messageIfEven = computed(() => {
    return (message) => {
      if (!isEven.value) return
      return message
    }
  })

  // ACTIONS
  function increment() {
    count.value++
  }

  return { count, isEven, messageIfEven, increment }
})

Notes

  • I think not everyone will remember the syntax for the imports so I added them.
  • I also added comments to make it really clear what is states, getters and actions.
  • isEven is a getter without arguments which works similar to a value.
  • messageIfEven(message) which works more like a method. It takes an argument and also uses the other getter isEven.
  • In the future we can get rid of .value after values and computed properties by using $ref(), but now we still has to deal with ref().

I hope this can help someone.

@posva posva mentioned this issue Jan 27, 2022
20 tasks
@posva
Copy link
Member

posva commented Jan 27, 2022

Thanks for the code sample! I added it to the docs roadmap

@posva posva closed this as completed Jan 27, 2022
@jaybo
Copy link

jaybo commented Mar 5, 2022

Is there any way to avoid re-enumerating all of the states, getters, and actions in the return, (or at least automate the entries)?

return { count, isEven, messageIfEven, increment }

@dmolesUC
Copy link

dmolesUC commented Jun 2, 2022

@jenstornell Is this transparent to store clients? I.e. does the code below still work just as if the store was defined statically with option syntax?

const store = useStoreCounter()
const { count, isEven, messageIfEven } = storeToRefs(store)
const { increment } = store

jxjj added a commit to UMN-LATIS/Camino that referenced this issue Jun 20, 2022
passing an option object gets complex and brittle with all the `this`. Moreover it's not entirely clear what's being returned.

Switching to function is clearer.

See: vuejs/pinia#978
@franck102
Copy link

It took quite a bit of googling before finding this, so definitely thumbs up.
I also believe the doc should clearly explain the relationship with the other style of store setup, namely out of

return { count, isEven, messageIfEven, increment }

how does Pinia decide what goes in "state", what goes in "getters", and what goes in "actions".

@Thy3634
Copy link

Thy3634 commented Aug 16, 2023

is it possable define a async store ?

export const useCounterStore = defineStore('counter', async () => {
  const count = ref(0)
  function increment() {
    count.value++
  }

  return { count, increment }
})
const counterStore = await useCounterStore()

Copy link
Member

posva commented Aug 16, 2023

not possible.

@dmoles
Copy link

dmoles commented Aug 22, 2023

@Thy3634 What are you trying to accomplish? You can certainly put async functions inside the store, if that helps.

@sisou
Copy link

sisou commented Oct 26, 2023

It does not raise a type error. It tells you the useStore() method now returns a promise, and then state on it is no longer unwrapped. But it also doesn't work at runtime 🤷

Either the types must be fixed somehow to disallow async setup, or a mention should be put in the docs that it's not supported.

As for what I want to accomplish? I want to run an async API call to initialize the store with a value, instead of undefined and having to call the API afterwards.

@posva
Copy link
Member

posva commented Oct 26, 2023

I think I removed the type check because it created other problems.

The doc already state that the setup function must return an object. It never shows an example of async setup. If you found that in an article or video, it would be worth letting the author know that is not possible.

As for your question, I believe it was asked before in the Discussions, so you should be able to find help there. Long story short, you will have to await for the data to be ready before mounting the component and there are many ways of doing this (before app.mount, in a navigation guard, in a component that is the child of Suspense). Feel free to open a discussion to gather information about this BTW.

I'm locking this one as it's outdated now.

@vuejs vuejs locked as resolved and limited conversation to collaborators Oct 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants