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

In-store setup #903

Closed
fl0cke opened this issue Dec 16, 2021 · 4 comments
Closed

In-store setup #903

fl0cke opened this issue Dec 16, 2021 · 4 comments

Comments

@fl0cke
Copy link

fl0cke commented Dec 16, 2021

What problem is this solving

Sometimes i need to react to changes to the state in a more granular way that is completely decoupled from the component that uses the store. For example, consider this simple use case:

export const useStore = defineStore('store', {
  state: () => ({
    start: null,
    destination: null,
    route: null,
  }),
  actions: {
    async fetchRoute() {
      // fetch route
    },
  },
})

Whenever start or destination changes, i want to fetch a new route, e.g.

watchEffect(() => {
  if (store.start && store.destination) {
    store.fetchRoute()
  }
})

There is currently no option to put this in the store directly. So i either have to pick a component to include the watcher or put it in app.ts where the store is created.

Proposed solution

Add a setup() like method to the store where i can put watchers and other initialization logic.

e.g.

export const useStore = defineStore('store', {
  state: () => ({
    start: null,
    destination: null,
    route: null,
  }),
  actions: {
    async fetchRoute() {
      // fetch route
    },
  },
  setup() {
    watchEffect(() => {
      if (this.start && this.destination) {
        this.fetchRoute()
      }
    })
  }
})

Describe alternatives you've considered

  • $subscribe:
    • requires a store instance
    • is triggered on every state change
  • put the watcher in app.ts or any component that uses the store
    • can get messy really quickly when you have multiple watchers for different stores
@posva
Copy link
Member

posva commented Dec 16, 2021

This is actually already supported with the setup syntax:

export const useStore = defineStore('store', () => {
  const start = ref(null)
  // ...

    async function fetchRoute() {
      // fetch route
    }

    watchEffect(() => {
      if (start.value && destination.value) {
        fetchRoute()
      }
    })
  return { start, destination }
  }
})

There is currently only one example of this in docs: https://pinia.esm.dev/introduction.html#basic-example and it's tracked at #829 to add more

@posva posva closed this as completed Dec 16, 2021
@dmolesUC
Copy link

dmolesUC commented Jun 2, 2022

@posva Is there a way to use the setup syntax to listen for whole-state changes cf. $subscribe()? (I mean, I can see ways to do it with additional layers of ref() but it feels like that would make read access to the store significantly messier.)

@posva
Copy link
Member

posva commented Jun 3, 2022

No, You can simply use a watcher

@dmolesUC
Copy link

dmolesUC commented Jun 3, 2022

Passing an explicit list of refs (as per these docs), you mean, like this?

watch([start, destination, route], ([newStart, newDestination, newRoute]) => {
  // ...
})

Or is there anything simpler / less repetitive? Would something like this work?

const storeDef = { start, destination, route }
watch(reactive(storeDef), (v, _) => {
  // do something with v.start etc.
})
return storeDef

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants