pinia
pinia copied to clipboard
Docs Roadmap
These are the documentation sections I want to add or improve
- [ ] Migrate to Vue.js theme
- [x] Use a neutral font (#873)
- [ ] Adapt instructions for Vue 2.7
- Cookbook
- Testing
- [x] Initializing the store before
- [ ] What is needed for Nuxt (maybe link to another page) (#910)
- [ ] Document action usage within setup stores cannot be stubbed https://github.com/vuejs/pinia/issues/2291
- [x] Advanced reactivity
- Show how to use composables inside option and setup stores
- [ ] Spltting the store into multiple files (#802)
- [ ] Allowing making a Store implement an interface (state, actions, or/and getters)
- [ ] Advanced SSR
- [ ] Hydrating differing state like
useLocalStorage()
- [x] Differences between Setup and Option stores
- [ ] Using stores before hydration https://github.com/vuejs/pinia/discussions/948
- [ ] Hydrating differing state like
- [ ] Handling Errors with API calls
- [ ] CDN installation for Vue 2 and Vue 3 #1051
- Testing
- [ ] State must be defined as a whole #1335
- [x] Setup Stores (https://github.com/vuejs/pinia/issues/978)
- Currently only Option stores are documented properly. It would be nice to have a switch somewhere or to mention them early on and link to a cookbook entry about advanced reactivity as these stores allow patterns that are impossible (or not intuitive) to achieve with the options API, like
watching
- Currently only Option stores are documented properly. It would be nice to have a switch somewhere or to mention them early on and link to a cookbook entry about advanced reactivity as these stores allow patterns that are impossible (or not intuitive) to achieve with the options API, like
- [ ] Being able to switch between syntaxes (option / setup store) (TBD if worth) https://github.com/vuejs/pinia/issues/1265
- [x] Reorganize the What is Pinia and Getting Started sections so the latter shows complete examples (#1195)
- [ ] Add note about
patch
modifying in place objects #1921
If you have suggestions about common use cases that are not covered or improvement / refactoring for the existing docs, please share
How to contribute
If you want to contribute to the docs, make sure first there is no active Pull Request or an existing branch on this repository. Fork this repo, and create a Pull Request. You can mark it as WIP/Not ready for review if you need more time to work on it. This would avoid having two people working on the same thing.
If you are uncertain about anything you wrote, just leave a review on your own Pull Request so I can help.
Translations
If you want to contribute translations, only the Chinese and English versions are hosted within the repository. Other translations should be hosted elsewhere following the translation guidelines
This is one thing I'd really appreciate clarified in the docs: mapStores.
I haven't had a chance to test it yet, but since the entire store is a computed property, I would assume that any modification of the store would result in re-rendering of all components subscribed to the store through mapStores. If this is the case, this is a pretty big caveat and should be documented clearly. I would suspect that due to the ease of using mapStores, a lot of users with big global stores might get into trouble.
I would assume that any modification of the store would result in re-rendering of all components subscribed to the store through mapStores
I don't think this is correct. If you had a "global" reactive
object and imported it into multiple components, it would only trigger a render if part of that object is tracked and that specifically is changed. For example if in one component you access globalObj.prop1
within the template or in a computed etc. the render will only trigger if you changed the prop1
property on that object, whether it be within the component or elsewhere. That's the beauty of reactivity.
This concept is the same for stores, when created there's a global instance of them. Even if you imported the same store in every component (with mapStores or otherwise) it'll only trigger a change if a property has been tracked within that component, and that specific property changed. For example, you access myStore.prop2
within the template, it will only render again if prop2
is changed. If you don't access anything on the store, nothing is tracked, so any changes to the store won't cause a render.
I'm using the words track
and trigger
on purpose as that's in line with how the docs explain it, see https://v3.vuejs.org/guide/reactivity.html#how-rendering-reacts-to-changes & subsequent pages.
I would assume that any modification of the store would result in re-rendering of all components subscribed to the store through mapStores
I don't think this is correct. If you had a "global"
reactive
object and imported it into multiple components, it would only trigger a render if part of that object is tracked and that specifically is changed. For example if in one component you accessglobalObj.prop1
within the template or in a computed etc. the render will only trigger if you changed theprop1
property on that object, whether it be within the component or elsewhere. That's the beauty of reactivity.This concept is the same for stores, when created there's a global instance of them. Even if you imported the same store in every component (with mapStores or otherwise) it'll only trigger a change if a property has been tracked within that component, and that specific property changed. For example, you access
myStore.prop2
within the template, it will only render again ifprop2
is changed. If you don't access anything on the store, nothing is tracked, so any changes to the store won't cause a render.I'm using the words
track
andtrigger
on purpose as that's in line with how the docs explain it, see https://v3.vuejs.org/guide/reactivity.html#how-rendering-reacts-to-changes & subsequent pages.
That's pretty amazing! Do you have any idea if this might hold true for Pinia in Vue 2 as well? After reading the docs it seems as though I might just need to be careful with property additions and array mutations. Arrays are a non issue, but I'm curious what'll happen if I set an optional prop after the fact.
I can certainly see myself using mapStores over the alternative, as it becomes more obvious when the code is accessing the store.
In any case, can't wait to move to a full Vue 3 + Pinia stack in the near future. Perfect reactivity and typescript support is going to be a major boon to development.
That's pretty amazing! Do you have any idea if this might hold true for Pinia in Vue 2 as well? After reading the docs it seems as though I might just need to be careful with property additions and array mutations. Arrays are a non issue, but I'm curious what'll happen if I set an optional prop after the fact.
Yep, same for Vue2 (with @vue/composition-api of course) there's some slight caveats as you mention but the general concept is the same. You can use set
from composition-api to add additional properties in Vue2.
I can certainly see myself using mapStores over the alternative, as it becomes more obvious when the code is accessing the store.
I prefer it. It also helps with conversion to composition api because I tend to declare stores in setup
like const userStore = useUserStore()
. So if I move a method for example into the setup function I just remove the this.
(so this.userStore.load()
becomes userStore.load()
for example) and it all works as before. Using the other map helpers needs a little more digging to find out where things came from originally.
In any case, can't wait to move to a full Vue 3 + Pinia stack in the near future. Perfect reactivity and typescript support is going to be a major boon to development.
Couldn't agree more.
I'm keen to write up some further documentation and cover some of these points. @posva Are there are works in progress for further documentation atm on any branches? And what's the best way to ask you a question if I run into something I'm unsure of while documenting?
-=-
And also to add a suggestion on something to document further:
When the store values differ on Server and Client, such as when using useStorage from Vueuse, the client store needs to be hydrated manually.
There's a section on that within the API reference part of the docs here: https://pinia.vuejs.org/api/interfaces/pinia.DefineStoreOptionsInPlugin.html#hydrate
However, I wanted to propose adding a small section on it under state within the Guide part of the docs.
I originally opened an issue for this, but see it may be better sat under this issue. I'm happy to open a PR to suggest potential documentation for that. Let me know what you think :)
@Jamiewarb I added an item to the list and updated the issue about how to contribute. Let me know if it's missing anything! I'm really keen on having cookbook entries contributed ๐
@posva Documented how to split up a repo in a type-safe way here.
What I'm currently missing from the docs (also from the vuex ones) are some general guidelines and best practices to work with a store. Questions that would be nice to answer in this context:
- For what kind of 'state' do you want to use a store over say component-wise reactive variables
- How much logic do you put in the actions of the store vs in composables that use the store (e.g. should a
login
action only setisLoggedIn
andcurrentUser
or should it also call the API to fetch the new user config [which would be handled in a different store] and do some general logging for stats etc).
Use a neutral font ([Docs]: Dank Mono is hard to read as someone visually and cognitively impaired #873)
Do you have some ideas about font? I think DM Mono might be nice because Nuxt.js use it.
Can we show an example of how to destructure actions
from a store
?
The doc only mentions that storeToRefs
skip actions
but it does not mention how you can destructure actions
from a store
.
It would be helpful to show an example at the bottom of this page: https://pinia.vuejs.org/core-concepts/#using-the-store
Yeah, it should be mentioned that you can just destructure actions
Could the addition and typing of getters with the plugin API be documented too? (https://github.com/vuejs/pinia/discussions/1196)
The plugin page (https://pinia.vuejs.org/core-concepts/plugins.html) contains a bullet with following text "Apply only to specific stores". However I can't seem to find an example on how to "filter" your stores so a plugin only gets applied to the store(s) you want instead of all of them. This is possible right, or am I misunderstanding something?
yeah, you can filter with the existance of an option (e.g. debounce) or explicitely filtering by id within the plugin if (store.$id === 'someid') <plugin code>
That's exactly what I had in mind in the meantime, I just wanted to make sure I was doing it the right way, thanks for the quick reply!
@posva when do you think the documentation should be ready for translations to other languages?
Is it a good idea to wait until this roadmap is completed?
Thanks for your answer.
Translations do not need to wait for this. You can work on them on your side, in a different repository, and publish them. We still need to publish a guide to let people translate docs.
Translations do not need to wait for this. You can work on them on your side, in a different repository, and publish them. We still need to publish a guide to let people translate docs.
Okay, though. In fact I actually felt the absence of a guide to help people do the translating, but for now I will just translate all content we have now, and updating when some new content is added to documentation. ๐
@posva
just make sure to search for existing translations first in order to collaborate ๐
Change the font for code hightlight please
https://pinia.vuejs.org/introduction.html#basic-example
- [ ] Spltting the store into multiple files (How to split store in different files? And the limits of object type inferenceย #802)
๐ I'm looking forward "native" way to split a store
The basic example should be rewritten in a clear structure that we can switch between Option and Composition API, overlap between option and composition is awful hard to read, confusing and overwhelm for new readers, my mind went blank despite an experienced programmer.
It feels like a tutorial written by someone's personal notebook? https://pinia.vuejs.org/introduction.html#basic-example
I agree #1265 is worth it and should follow Vue way.
@posva is the repository already receiving translations for the documentation?
I added a note to the issue. The rest is at https://vuejs.org/translations/ ๐
I added a note to the issue. The rest is at https://vuejs.org/translations/ :slightly_smiling_face:
@posva I just started translating the Vue.js 3 documentation into Portuguese, I already mentioned our programmers' colleagues are working on the project but until now I did not receive any feedback.
The website is being served on Vue.js 3 Docs (Portuguรชs)
@nazarepiedady please refer to https://github.com/vuejs-translations/guidelines/blob/main/README.md. It's great you are working on the translation but this is pinia repo not vuejs/core. As the guidelines say, once you have more than 50% translated, open a PR to docs to add a link
Also please, don't ping every time, it creates a notification but people will reply on the repositories without the ping ๐
I don't know if this has been considered, but it seems like Pinia can be used in a "namespace" way of handling stores that Vuex did. I really wanted to separate stores that are based off the same store file... eg:
// selection.store.js
export const useStore = ({ namespace }={}) => {
const storeID = `selection${namespace ? `:${namespace}` : '' }`;
const store = defineStore(storeID, {
state: () => ({
current: undefined,
previous: undefined,
// ...
}),
getters: {
// ....
},
actions: {
// ....
},
})();
return store;
};
Instead of writing 5 different stores that do the same thing using the same content I just do this:
import { useStore } from 'stores/selection.store.js';
// ... define and use each store wherever needed in a separate namespace
const selectOneStore = useStore({ namespace: 'one' }); // storeID => selection:one
const selectTwoStore = useStore({ namespace: 'two' }); // storeID => selection:two
const selectThreeStore = useStore({ namespace: 'three' }); // storeID => selection:three
const selectFourStore = useStore({ namespace: 'four' }); // storeID => selection:four
// ... do whatever with stores wherever each store is being used
// ... if the same is being used without any namespacing
const selectionStore = useStore(); // storeID => selection
... and now have stores selection:one
, selection:two
, selection:three
, selection:four
and selection
that are independent from each other but use the same logic.
They can be used by different things that handle completely different use cases, but use the same logic. They also appear in dev tools as different stores. The best thing is there is nothing weird or hacky on Pinia, it's just how one defines the stores.
I wish this is documented somewhere so that users can use this method of defining stores and also help transition Vuex code.
@posva Hi I recently had to use pinia in nuxt2. I faced a problem because I had store which had to use local storage and it led me to ssr problems. It wasn't updating data from localstorage after hydration, so I was digging in doc and found hydate method, but I only found how to use it in option api. I couldn't figure out solution for composition api. Could you please tell me if it's possibile solve it with composition api and how? Also it would be great to update docs with informations about it =)
Thanks!
That's already documented: https://pinia.vuejs.org/cookbook/composables.html#ssr
:D ok thanks I don't know why I couldn't find it thanks a lot again!