[Vuex] Vuex 5 #270
Replies: 46 comments 121 replies
-
I can see some similarities between this RFC and https://github.com/posva/pinia. Are them somehow related? |
Beta Was this translation helpful? Give feedback.
-
As a first skim through it seems that it covers most of use cases and concerns. Great work on the proposal. Question: Why are we targeting Vue 3.1 release? |
Beta Was this translation helpful? Give feedback.
-
Please avoid using |
Beta Was this translation helpful? Give feedback.
-
In one of my projects a specific part of the app uses a separate, second store (as in |
Beta Was this translation helpful? Give feedback.
-
I am missing two key things compared to Vuex 3:
I am also not a fan of global mixins on Vuex (called Plugins in RFC), I am not convinced this is needed in Vuex since it adds unnecessary responsibility which should be in its own layer abstracted from Vuex and does not operate on the same level of abstraction as data management ( |
Beta Was this translation helpful? Give feedback.
-
Great work, I am really excited to see this RFC. In my humble opinion, because Vuex 5 represents so much "new code" and represents a major shift in API, we should simplify to just composition stores. Git rid of all options-based API, and let there be one way to do things. People will already have to do major refactors when going from 3/4 to 5, so why not switch to composition style stores while we have the opportunity? Sure options syntax appears more familiar right now, but having a single way to do things going forward has major benefits. To help ease the transition, code mods or adapters could be created, or maybe just recommend Vuex 4 if you want options syntax. For those using the options syntax for their Vue components, there is no real disadvantage. This would have no bearing on their decision to use composition or options API in Vue components. They can still use options syntax to their hearts content. I don't believe Vuex 5 needs to be part of the dilemma of options vs. composition API, because component definition is not the same domain as global state definition. If I'm not mistaken, the long-term goal for Vue is to see options API gradually disappear in favor of composition. Perhaps Vuex 5 could be a little more future-oriented, and sort of help introduce composition to devs still using options syntax. In this way, should they choose to switch Vue components from options to composition API, they will be able to rely on some previous knowledge of how setup functions/refs, etc. work. In addition, dropping the options API would also allow for faster development cycles, fewer edge case bugs, smaller bundle sizes, and easier contribution. |
Beta Was this translation helpful? Give feedback.
-
I am confused on why we want to get rid of mutations. Some processes need to run synchronously don’t they? E.g. A person should pay before placing the order. The createVuex is a good idea because it follows the same canonical as creating VueJs 3 app. |
Beta Was this translation helpful? Give feedback.
-
RE the migration. It seems that this proposal is fully opt in. It it so different it is actually simple to migrate in user land progressivelu. Alias old Vuex to something like This would all the use of Vuex 5, allowing apps to progressively migrate and use the new version without hassle. This will also allow existing stores do be migrated 1 by 1. The reason I mention this is to avoid the need for a migration strategy other than use A or B version. Yes there will be a minor overhead of dependencies included at runtime but Vuex isn't a huge dependency. In big applications Vuex modules / stores will be code split also helping reduce that burden |
Beta Was this translation helpful? Give feedback.
-
One benefit of Vuex was a single way if doing things, the only thing I don't like about this proposal is that there is now two ways to do something and an increased surface area of knowledge to share. In larger organisations I can imagine it'll be hard to enforce this, would there be a way to split this into multiple packages. This way we could enforce a single way to do things at application level and reduce the surface area of functionality depending on the package imported. If the package doesn't exist in the dependency chain it'll make it much more difficult to use the alternative API. |
Beta Was this translation helpful? Give feedback.
-
I wonder if we are redesigning const useCounter = defineStore({
key: 'counter',
state: () => ({
count: 1
}),
getters: {
double() {
return this.count * 2
}
},
actions: {
increment() {
this.count++
}
}
})
// equivalent composition store
import { ref, computed } from 'vue'
import { defineStore } from 'vuex'
const useCounter = defineStore('counter', () => {
const count = ref(1)
const double = computed(() => count.value * 2)
function increment() {
count.value++
}
return {
count,
double,
increment
}
}) Looks like the same as class CounterStore {
count = 1
get double {
return this.count * 2
}
increment() {
this.count++
}
// advanced usage
storeB = useStoreB()
constructor(context) {
// access vuex plugin in context
const {$axios} = context
}
get crossStoreGetter() {
return this.storeB.fooB
}
} Implementation-wise, I would argue that class API is quite similar to composition API. State inspection, mutation logging and time-travel can be implemented by proxy. Arguably the benefit of using class is:
Downside:
|
Beta Was this translation helpful? Give feedback.
-
Now that mutations are gone, how will the ordering between actions (e.g. for time-travelling purposes) work? Ordering sync actions, or actions that otherwise mutate all data in the same tick, is safe. But, otherwise, there could be data hazards in considering actions as atomic changes, like mutations in current Vuex. Consider the following async action: // ...
async myAction () {
this.a = something()
this.b = await somethingVerySlow(this.a)
const x = await anotherSlowOperation()
this.c = anotherThing(this.b, x)
}, Another component could dispatch a sync action (and, therefore, mutate state) between the time In that hypothetical scenario, there could be problems in ordering the async action and the posterior sync action, specially if the latter read and/or write I can see two paths:
It have some cons, like the extra noise and the risk of causing a data inconsistency during a partial rollback. Pinia can solve those cons, as far as I know, with the Data changes caused by the same action during the same tick could be grouped by some heuristics -- it'd probably require running something like
I think this is worse than the original problem. The text suggests that a separate RFC can be opened for discussing devtools support for Vuex v5. I can pause discussing this topic for now, but I'd like to mention it because it involves some key changes in v5 (the absence of mutations). |
Beta Was this translation helpful? Give feedback.
-
This is probably more a vocabulary issue, but I got confused by the fact that the store instanciation is now done in component code, and that despite it is done in several components, the store is instanciated only once, as explained in the Automatic store registration part. As an end-user and not a Vuex contributor, I would find it easier to understand if we use the words "create → register" instead of "define → instanciate". <script setup>
import { useCounter } from '@/stores/counter'
const counter = useCounter()
</script> This is very neat compared to the Options API that requires to call |
Beta Was this translation helpful? Give feedback.
-
I really like that we keep the support for Options API for those of us who are not yet ready to learn the Composition API and want to stay productive with their projects. In a year or two, I'll sit down with a lot of coffee, and although I understand the changes, the motivations and how things in the Composition API work, I'll then nonetheless get out of my way to learn it in practice and ensure that I can work with it productively. Right now it would just cause me unnecessary stress. Thank you guys! |
Beta Was this translation helpful? Give feedback.
-
I actually really like this RFC! It is fully TS compatible, which is awesome. Tho, my concern is about code splitting. In large Vue projects, Vuex single module can get quite big, so in my team, we split Potentially, you could work around this in composition API manually. In Options API, we could have potentailly const state = { counter: 0 }
const getters = defineGetters(state, {
biggerCounter() {
return this.counter + 10
}
})
const actions = defineActions(state, getters, {
increment() {
this.counter += 1
}
}) But that's just my concerns, that could be solved with some kind of 'per project' wrapper. Anyway, great job guys! I think it's good direction! ^^ |
Beta Was this translation helpful? Give feedback.
-
thanks for the great work. some questions:
import { useCounter } from '@/stores/Counter'
export default {
setup() {
const counter = useCounter()
counter.count // <- 1
}
}
// useStore
import { useStore } from 'vuex'
export default {
setup() {
const counterStore = useStore('counter')
counterStore.count // <- 1
}
}
const vuex = createVuex()
vuex.store({
// some dynamic config
}) Thanks & Thumps up! |
Beta Was this translation helpful? Give feedback.
-
Is there an estimated timeline when feedbacks will be consolidated and an alpha build of this RFC will be out? I believe many of us are willing to try such build on our side project(s) and provide real-world usage feedback, which might be useful in moving discussion forward. |
Beta Was this translation helpful? Give feedback.
-
Is vuex going to support state machines in the future. Or will you create your own mechanism |
Beta Was this translation helpful? Give feedback.
-
Dropping my $0.02 here, though nobody asked. Vuex was the first time I used a state management library and things just felt "perfect." I was in love. It's gotten even better over time. I would say that Pinia (with some small tradeoffs) improved on Vuex, and we've seen a taste of that incorporated in Vuex 4 with more to come in Vuex 5. The only thing I'd like to ask, is if there's an API option that keeps a boundary between "data" and "not-data". const useCounter = defineStore('counter', () => {
const count = ref(1)
const double = computed(() => count.value * 2)
function increment() {
count.value++
}
return {
count,
double,
increment
}
}) It's hard to visually distinguish what is Personally, I've taken to doing this in my Vue apps: const state = reactive({
users: [],
loading: false,
error: false
})
const computeds = {
usersOver18: computed(() => state.users.filter(it => it.age > 18))
}
function doSomething() {
console.log("foo")
}
return { state, computeds, doSomething } Because it's less cognitive overhead to figure out which things are plain state, which things are computed, which things are methods, etc. In your template, you press Compared to using
const users = ref([])
const loading = ref(false)
const error = ref(false)
const usersOver18 = computed(() => users.value.filter(it => it.age > 18))
function doSomething() {
console.log("foo")
}
return { users, loading, error, usersOver18, doSomething } |
Beta Was this translation helpful? Give feedback.
-
Hi, I'm confused about how long can we use vuex5? How should I choose Pinia2 and vuex4 in my new vue3 project? |
Beta Was this translation helpful? Give feedback.
-
Could this RFC be updated to reflect pinia@2.0.0 ? I think pinia pretty much nailed what Vuex 5 should be, and it's kind of weird that this RFC is out of sync. Also, one feature that I don't like (and that is not part of pinia) is the const storeA = useStoreA();
storeA.storeB.valueFromStoreB // Will this work? If it does leak, then to me this feature has more cons than pros. It creates a lot of unnecessary coupling and bloats store A for no good reason. If you need store B, then just use it. If it does not leak, then I guess it's an "ok" feature but again, to me this adds unnecessary complexity. Just the fact that the name is inferred (useGreeter -> greeter) makes it weird to me. I have never needed that feature in pinia, and unless people are actually asking for it, I'm not sure it should be part of Vuex 5. Also, completely different topic: Since Vuex 5 will be so much different from Vuex 4, why not put Vuex end of life and just use Pinia instead? Migrating from vuex 4 to 5 will feel like using a brand new library anyway. |
Beta Was this translation helpful? Give feedback.
-
Any update on GA or alpha/beta release ? |
Beta Was this translation helpful? Give feedback.
-
Thanks for this RFC! After read the RFC and discussions, I wonder why not direct return store instance in defineStore function? Just like this: // singleton store registry
const vuex = createVuex()
// define and register the store
const counter = vuex.defineStore(...)
// direct use counter store
counter.count // 1
counter.double // 2 And I see Vuex 4 provide an import store from '@/my-app-store/index'
export default {
setup () {
// direct use store example
return {
count: computed(() => store.state.count),
}
}
} |
Beta Was this translation helpful? Give feedback.
-
I create a extension for pinia, maybe can add to this RFC? pinia-di: DI(dependency-injection) for pinia, work with vue@3. Why?
For example, i have ten same components in my page, they have the same data structure but independent state, it is very cumbersome to manage them in an array of a common store. Another problem, for large project, i want to release the memory of state(auto unmount store) after the component unmount. If we manage that manually, it is cumbersome too. Based on my previous project experience, i take the Core Concepts
InjectionContext:
|
Beta Was this translation helpful? Give feedback.
-
I know it's too soon to talk about the release of Vuex 5 but since there hasn't been any recent announcements I was looking for new updates and I come across to some tweets from Evan You on Vuex and Pinia that seem confusing |
Beta Was this translation helpful? Give feedback.
-
I design a lib based on Vuex, and has similar usage as Pinia (or even simpler). It use "stateful singletons" by default, but can fully avoids "stateful singletons" by switch to advanced usage if necessary. export const counterStore = hamiVuex.store({
// unique name of the store, will appear in devtools
$name: 'counter',
// define the state with a function that returns a fresh state
$state() {
return { count: 0 }
}
// define a getter, similar to Vue computed
get double() {
return this.count * 2
},
// define an action, similar to Vuex action
increment() {
// $patch is builtin Vuex mutation, used for update state
this.$patch(state => {
state.count = this.count + 1
})
},
}) Why use "stateful singleton"? Stateful singletons are simpler and more convenient to use, and only perform poorly in terms of Vue SSR. Vue SSR is not required for most single-page applications, so you can use "stateful singleton" with confidence and switch to advanced usage if necessary. Repo / Document / Design considerations: Thanks all ideas in this RFC discussion which bringing me a lot of inspiration! |
Beta Was this translation helpful? Give feedback.
-
just suggest Pinia officially or merge Vuex 5 with Pinia in one project |
Beta Was this translation helpful? Give feedback.
-
Hi, as vuex5 is based on Pinia, will it handle splitting store in different files ? |
Beta Was this translation helpful? Give feedback.
-
Is this proposal still an active one @kiaking ? @posva you may also know the status here. I think it would be great if the Vuex docs mentioned if it was being sunset for Pinia going forward as well, if all the energy for state management is going into Pinia as a first party library |
Beta Was this translation helpful? Give feedback.
-
There will be no Vuex 5 https://www.youtube.com/watch?v=BUUupT4zfA0&t=1041s |
Beta Was this translation helpful? Give feedback.
-
We're closing the RFC due to Pinia becoming the next official state management lib for Vue. Pinia has almost the exact same or enhanced API as Vuex 5, described in this RFC. You could simply consider Pinia as Vuex 5 with a different name. |
Beta Was this translation helpful? Give feedback.
-
UPDATE
We're closing the RFC due to Pinia becoming the next official state management lib for Vue.
Pinia has almost the exact same or enhanced API as Vuex 5, described in this RFC. You could simply consider Pinia as Vuex 5 with a different name.
This is the discussion thread for the new Vuex 5 RFC.
Beta Was this translation helpful? Give feedback.
All reactions