Comparing version 0.0.1 to 0.0.2
/*! | ||
* pinia v0.0.1 | ||
* pinia v0.0.2 | ||
* (c) 2019 Eduardo San Martin Morote | ||
@@ -101,3 +101,3 @@ * @license MIT | ||
function innerPatch(target, patchToApply) { | ||
// TODO: get all keys | ||
// TODO: get all keys like symbols as well | ||
for (var key in patchToApply) { | ||
@@ -121,3 +121,3 @@ var subPatch = patchToApply[key]; | ||
*/ | ||
function createStore(id, buildState, getters | ||
function buildStore(id, buildState, getters | ||
// methods: Record<string | symbol, StoreMethod> | ||
@@ -195,44 +195,18 @@ ) { | ||
/** | ||
* | ||
* Creates a `useStore` function that retrieves the store instance | ||
* @param id id of the store we are creating | ||
* @param buildState function that returns a state | ||
* @param getters optional object of getters | ||
*/ | ||
function makeStore(id, buildState, getters) { | ||
function createStore(id, buildState, getters) { | ||
if (getters === void 0) { getters = {}; } | ||
var store; | ||
function useStore() { | ||
if (!store) | ||
store = createStore(id, buildState, getters); | ||
return function useStore(forceNewStore) { | ||
if (forceNewStore === void 0) { forceNewStore = false; } | ||
if (!store || forceNewStore) | ||
store = buildStore(id, buildState, getters); | ||
return store; | ||
} | ||
function clear() { | ||
store = undefined; | ||
} | ||
return { | ||
useStore: useStore, | ||
clear: clear, | ||
}; | ||
} | ||
// export const store = createStore('main', initialState) | ||
// type StateI = ReturnType<typeof buildState> | ||
// const buildState = () => ({ | ||
// items: ['thing 1'], | ||
// }) | ||
// export const cartStore = createStore('cart', buildState, { | ||
// amount: state => state.items.length, | ||
// }) | ||
// cartStore.nonueo | ||
// cartStore.amount.value * 2 | ||
// store.patch({ | ||
// toggle: 'off', | ||
// nested: { | ||
// a: { | ||
// b: { | ||
// c: 'one', | ||
// }, | ||
// }, | ||
// }, | ||
// }) | ||
exports.createStore = createStore; | ||
exports.makeStore = makeStore; |
/*! | ||
* pinia v0.0.1 | ||
* pinia v0.0.2 | ||
* (c) 2019 Eduardo San Martin Morote | ||
@@ -97,3 +97,3 @@ * @license MIT | ||
function innerPatch(target, patchToApply) { | ||
// TODO: get all keys | ||
// TODO: get all keys like symbols as well | ||
for (var key in patchToApply) { | ||
@@ -117,3 +117,3 @@ var subPatch = patchToApply[key]; | ||
*/ | ||
function createStore(id, buildState, getters | ||
function buildStore(id, buildState, getters | ||
// methods: Record<string | symbol, StoreMethod> | ||
@@ -191,43 +191,18 @@ ) { | ||
/** | ||
* | ||
* Creates a `useStore` function that retrieves the store instance | ||
* @param id id of the store we are creating | ||
* @param buildState function that returns a state | ||
* @param getters optional object of getters | ||
*/ | ||
function makeStore(id, buildState, getters) { | ||
function createStore(id, buildState, getters) { | ||
if (getters === void 0) { getters = {}; } | ||
var store; | ||
function useStore() { | ||
if (!store) | ||
store = createStore(id, buildState, getters); | ||
return function useStore(forceNewStore) { | ||
if (forceNewStore === void 0) { forceNewStore = false; } | ||
if (!store || forceNewStore) | ||
store = buildStore(id, buildState, getters); | ||
return store; | ||
} | ||
function clear() { | ||
store = undefined; | ||
} | ||
return { | ||
useStore: useStore, | ||
clear: clear, | ||
}; | ||
} | ||
// export const store = createStore('main', initialState) | ||
// type StateI = ReturnType<typeof buildState> | ||
// const buildState = () => ({ | ||
// items: ['thing 1'], | ||
// }) | ||
// export const cartStore = createStore('cart', buildState, { | ||
// amount: state => state.items.length, | ||
// }) | ||
// cartStore.nonueo | ||
// cartStore.amount.value * 2 | ||
// store.patch({ | ||
// toggle: 'off', | ||
// nested: { | ||
// a: { | ||
// b: { | ||
// c: 'one', | ||
// }, | ||
// }, | ||
// }, | ||
// }) | ||
export { createStore, makeStore }; | ||
export { createStore }; |
/*! | ||
* pinia v0.0.1 | ||
* pinia v0.0.2 | ||
* (c) 2019 Eduardo San Martin Morote | ||
* @license MIT | ||
*/ | ||
/*! | ||
* pinia v0.0.1 | ||
* (c) 2019 Eduardo San Martin Morote | ||
* @license MIT | ||
*/ | ||
import{ref as t,watch as e,computed as n}from"@vue/composition-api"; | ||
@@ -25,2 +20,2 @@ /*! ***************************************************************************** | ||
and limitations under the License. | ||
***************************************************************************** */var o=function(){return(o=Object.assign||function(t){for(var e,n=1,o=arguments.length;n<o;n++)for(var u in e=arguments[n])Object.prototype.hasOwnProperty.call(e,u)&&(t[u]=e[u]);return t}).apply(this,arguments)};function u(t){return t&&"object"==typeof t&&"[object Object]"===Object.prototype.toString.call(t)&&"function"!=typeof t.toJSON}var r,i=("undefined"!=typeof window?window:"undefined"!=typeof global?global:{__VUE_DEVTOOLS_GLOBAL_HOOK__:void 0}).__VUE_DEVTOOLS_GLOBAL_HOOK__;function a(a,c,f){void 0===f&&(f={});var s=t(c()),p=!0,l=[];e((function(){return s.value}),(function(t){p&&l.forEach((function(e){e({storeName:a,type:"🧩 in place",payload:{}},t)}))}),{deep:!0,flush:"sync"});var d={id:a,state:s.value,patch:function(t){p=!1,function t(e,n){for(var o in n){var r=n[o],i=e[o];u(i)&&u(r)?e[o]=t(i,r):e[o]=r}return e}(s.value,t),p=!0,l.forEach((function(e){e({storeName:a,type:"⤵️ patch",payload:t},s.value)}))},subscribe:function(t){l.push(t)},reset:function(){l=[],s.value=c()}},v={},_=function(t){f[t];v[t]=n((function(){return f[t](s.value)}))};for(var m in f)_(m);var O=o(o({},d),v);return Object.defineProperty(O,"state",{get:function(){return s.value},set:function(t){p=!1,s.value=t,p=!0}}),function(t){i&&(r||(r={_devtoolHook:i,_vm:{$options:{computed:{}}},_mutations:{},_modulesNamespaceMap:{},_modules:{get:function(t){return t in r._modulesNamespaceMap}},state:{},replaceState:function(){},registerModule:function(){},unregisterModule:function(){}},i.emit("vuex:init",r)),r.state[t.id]=t.state,r.registerModule(t.id,t),Object.defineProperty(r.state,t.id,{get:function(){return t.state},set:function(e){return t.state=e}}),r._modulesNamespaceMap[t.id+"/"]=!0,i.on("vuex:travel-to-state",(function(e){t.state=e[t.id]})),t.subscribe((function(e,n){r.state[t.id]=n,i.emit("vuex:mutation",o(o({},e),{type:"["+e.storeName+"] "+e.type}),r.state)})))}(O),O}function c(t,e,n){var o;return void 0===n&&(n={}),{useStore:function(){return o||(o=a(t,e,n)),o},clear:function(){o=void 0}}}export{a as createStore,c as makeStore}; | ||
***************************************************************************** */var o=function(){return(o=Object.assign||function(t){for(var e,n=1,o=arguments.length;n<o;n++)for(var u in e=arguments[n])Object.prototype.hasOwnProperty.call(e,u)&&(t[u]=e[u]);return t}).apply(this,arguments)};function u(t){return t&&"object"==typeof t&&"[object Object]"===Object.prototype.toString.call(t)&&"function"!=typeof t.toJSON}var i,r=("undefined"!=typeof window?window:"undefined"!=typeof global?global:{__VUE_DEVTOOLS_GLOBAL_HOOK__:void 0}).__VUE_DEVTOOLS_GLOBAL_HOOK__;function a(a,c,f){void 0===f&&(f={});var s=t(c()),p=!0,l=[];e((function(){return s.value}),(function(t){p&&l.forEach((function(e){e({storeName:a,type:"🧩 in place",payload:{}},t)}))}),{deep:!0,flush:"sync"});var d={id:a,state:s.value,patch:function(t){p=!1,function t(e,n){for(var o in n){var i=n[o],r=e[o];u(r)&&u(i)?e[o]=t(r,i):e[o]=i}return e}(s.value,t),p=!0,l.forEach((function(e){e({storeName:a,type:"⤵️ patch",payload:t},s.value)}))},subscribe:function(t){l.push(t)},reset:function(){l=[],s.value=c()}},v={},_=function(t){f[t];v[t]=n((function(){return f[t](s.value)}))};for(var m in f)_(m);var O=o(o({},d),v);return Object.defineProperty(O,"state",{get:function(){return s.value},set:function(t){p=!1,s.value=t,p=!0}}),function(t){r&&(i||(i={_devtoolHook:r,_vm:{$options:{computed:{}}},_mutations:{},_modulesNamespaceMap:{},_modules:{get:function(t){return t in i._modulesNamespaceMap}},state:{},replaceState:function(){},registerModule:function(){},unregisterModule:function(){}},r.emit("vuex:init",i)),i.state[t.id]=t.state,i.registerModule(t.id,t),Object.defineProperty(i.state,t.id,{get:function(){return t.state},set:function(e){return t.state=e}}),i._modulesNamespaceMap[t.id+"/"]=!0,r.on("vuex:travel-to-state",(function(e){t.state=e[t.id]})),t.subscribe((function(e,n){i.state[t.id]=n,r.emit("vuex:mutation",o(o({},e),{type:"["+e.storeName+"] "+e.type}),i.state)})))}(O),O}function c(t,e,n){var o;return void 0===n&&(n={}),function(u){return void 0===u&&(u=!1),o&&!u||(o=a(t,e,n)),o}}export{c as createStore}; |
/*! | ||
* pinia v0.0.1 | ||
* pinia v0.0.2 | ||
* (c) 2019 Eduardo San Martin Morote | ||
@@ -98,3 +98,3 @@ * @license MIT | ||
function innerPatch(target, patchToApply) { | ||
// TODO: get all keys | ||
// TODO: get all keys like symbols as well | ||
for (var key in patchToApply) { | ||
@@ -118,3 +118,3 @@ var subPatch = patchToApply[key]; | ||
*/ | ||
function createStore(id, buildState, getters | ||
function buildStore(id, buildState, getters | ||
// methods: Record<string | symbol, StoreMethod> | ||
@@ -192,45 +192,19 @@ ) { | ||
/** | ||
* | ||
* Creates a `useStore` function that retrieves the store instance | ||
* @param id id of the store we are creating | ||
* @param buildState function that returns a state | ||
* @param getters optional object of getters | ||
*/ | ||
function makeStore(id, buildState, getters) { | ||
function createStore(id, buildState, getters) { | ||
if (getters === void 0) { getters = {}; } | ||
var store; | ||
function useStore() { | ||
if (!store) | ||
store = createStore(id, buildState, getters); | ||
return function useStore(forceNewStore) { | ||
if (forceNewStore === void 0) { forceNewStore = false; } | ||
if (!store || forceNewStore) | ||
store = buildStore(id, buildState, getters); | ||
return store; | ||
} | ||
function clear() { | ||
store = undefined; | ||
} | ||
return { | ||
useStore: useStore, | ||
clear: clear, | ||
}; | ||
} | ||
// export const store = createStore('main', initialState) | ||
// type StateI = ReturnType<typeof buildState> | ||
// const buildState = () => ({ | ||
// items: ['thing 1'], | ||
// }) | ||
// export const cartStore = createStore('cart', buildState, { | ||
// amount: state => state.items.length, | ||
// }) | ||
// cartStore.nonueo | ||
// cartStore.amount.value * 2 | ||
// store.patch({ | ||
// toggle: 'off', | ||
// nested: { | ||
// a: { | ||
// b: { | ||
// c: 'one', | ||
// }, | ||
// }, | ||
// }, | ||
// }) | ||
exports.createStore = createStore; | ||
exports.makeStore = makeStore; | ||
@@ -237,0 +211,0 @@ return exports; |
/*! | ||
* pinia v0.0.1 | ||
* pinia v0.0.2 | ||
* (c) 2019 Eduardo San Martin Morote | ||
* @license MIT | ||
*/ | ||
/*! | ||
* pinia v0.0.1 | ||
* (c) 2019 Eduardo San Martin Morote | ||
* @license MIT | ||
*/ | ||
var Pinia=function(t,e){"use strict"; | ||
@@ -25,2 +20,2 @@ /*! ***************************************************************************** | ||
and limitations under the License. | ||
***************************************************************************** */var n=function(){return(n=Object.assign||function(t){for(var e,n=1,o=arguments.length;n<o;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};function o(t){return t&&"object"==typeof t&&"[object Object]"===Object.prototype.toString.call(t)&&"function"!=typeof t.toJSON}var r,u=("undefined"!=typeof window?window:"undefined"!=typeof global?global:{__VUE_DEVTOOLS_GLOBAL_HOOK__:void 0}).__VUE_DEVTOOLS_GLOBAL_HOOK__;function i(t,i,a){void 0===a&&(a={});var c=e.ref(i()),f=!0,s=[];e.watch((function(){return c.value}),(function(e){f&&s.forEach((function(n){n({storeName:t,type:"🧩 in place",payload:{}},e)}))}),{deep:!0,flush:"sync"});var p={id:t,state:c.value,patch:function(e){f=!1,function t(e,n){for(var r in n){var u=n[r],i=e[r];o(i)&&o(u)?e[r]=t(i,u):e[r]=u}return e}(c.value,e),f=!0,s.forEach((function(n){n({storeName:t,type:"⤵️ patch",payload:e},c.value)}))},subscribe:function(t){s.push(t)},reset:function(){s=[],c.value=i()}},l={},d=function(t){a[t];l[t]=e.computed((function(){return a[t](c.value)}))};for(var v in a)d(v);var _=n(n({},p),l);return Object.defineProperty(_,"state",{get:function(){return c.value},set:function(t){f=!1,c.value=t,f=!0}}),function(t){u&&(r||(r={_devtoolHook:u,_vm:{$options:{computed:{}}},_mutations:{},_modulesNamespaceMap:{},_modules:{get:function(t){return t in r._modulesNamespaceMap}},state:{},replaceState:function(){},registerModule:function(){},unregisterModule:function(){}},u.emit("vuex:init",r)),r.state[t.id]=t.state,r.registerModule(t.id,t),Object.defineProperty(r.state,t.id,{get:function(){return t.state},set:function(e){return t.state=e}}),r._modulesNamespaceMap[t.id+"/"]=!0,u.on("vuex:travel-to-state",(function(e){t.state=e[t.id]})),t.subscribe((function(e,o){r.state[t.id]=o,u.emit("vuex:mutation",n(n({},e),{type:"["+e.storeName+"] "+e.type}),r.state)})))}(_),_}return t.createStore=i,t.makeStore=function(t,e,n){var o;return void 0===n&&(n={}),{useStore:function(){return o||(o=i(t,e,n)),o},clear:function(){o=void 0}}},t}({},VueCompositionApi); | ||
***************************************************************************** */var n=function(){return(n=Object.assign||function(t){for(var e,n=1,o=arguments.length;n<o;n++)for(var u in e=arguments[n])Object.prototype.hasOwnProperty.call(e,u)&&(t[u]=e[u]);return t}).apply(this,arguments)};function o(t){return t&&"object"==typeof t&&"[object Object]"===Object.prototype.toString.call(t)&&"function"!=typeof t.toJSON}var u,r=("undefined"!=typeof window?window:"undefined"!=typeof global?global:{__VUE_DEVTOOLS_GLOBAL_HOOK__:void 0}).__VUE_DEVTOOLS_GLOBAL_HOOK__;function i(t,i,a){void 0===a&&(a={});var c=e.ref(i()),f=!0,s=[];e.watch((function(){return c.value}),(function(e){f&&s.forEach((function(n){n({storeName:t,type:"🧩 in place",payload:{}},e)}))}),{deep:!0,flush:"sync"});var p={id:t,state:c.value,patch:function(e){f=!1,function t(e,n){for(var u in n){var r=n[u],i=e[u];o(i)&&o(r)?e[u]=t(i,r):e[u]=r}return e}(c.value,e),f=!0,s.forEach((function(n){n({storeName:t,type:"⤵️ patch",payload:e},c.value)}))},subscribe:function(t){s.push(t)},reset:function(){s=[],c.value=i()}},d={},l=function(t){a[t];d[t]=e.computed((function(){return a[t](c.value)}))};for(var v in a)l(v);var _=n(n({},p),d);return Object.defineProperty(_,"state",{get:function(){return c.value},set:function(t){f=!1,c.value=t,f=!0}}),function(t){r&&(u||(u={_devtoolHook:r,_vm:{$options:{computed:{}}},_mutations:{},_modulesNamespaceMap:{},_modules:{get:function(t){return t in u._modulesNamespaceMap}},state:{},replaceState:function(){},registerModule:function(){},unregisterModule:function(){}},r.emit("vuex:init",u)),u.state[t.id]=t.state,u.registerModule(t.id,t),Object.defineProperty(u.state,t.id,{get:function(){return t.state},set:function(e){return t.state=e}}),u._modulesNamespaceMap[t.id+"/"]=!0,r.on("vuex:travel-to-state",(function(e){t.state=e[t.id]})),t.subscribe((function(e,o){u.state[t.id]=o,r.emit("vuex:mutation",n(n({},e),{type:"["+e.storeName+"] "+e.type}),u.state)})))}(_),_}return t.createStore=function(t,e,n){var o;return void 0===n&&(n={}),function(u){return void 0===u&&(u=!1),o&&!u||(o=i(t,e,n)),o}},t}({},VueCompositionApi); |
@@ -1,27 +0,1 @@ | ||
import { StateTree, Store, StoreGetters, StoreGetter } from './types'; | ||
/** | ||
* NOTE: by allowing users to name stores correctly, they can nest them the way | ||
* they want, no? like user/cart | ||
*/ | ||
declare type CombinedStore<Id extends string, S extends StateTree, G extends Record<string, StoreGetter<S>>> = Store<Id, S> & StoreGetters<S, G>; | ||
/** | ||
* Creates a store instance | ||
* @param id unique identifier of the store, like a name. eg: main, cart, user | ||
* @param initialState initial state applied to the store, Must be correctly typed to infer typings | ||
*/ | ||
export declare function createStore<Id extends string, S extends StateTree, G extends Record<string, StoreGetter<S>>>(id: Id, buildState: () => S, getters?: G): CombinedStore<Id, S, G>; | ||
/** | ||
* The api needs more work we must be able to use the store easily in any | ||
* function by calling `useStore` to get the store Instance and we also need to | ||
* be able to reset the store instance between requests on the server | ||
*/ | ||
/** | ||
* | ||
* @param id id of the store we are creating | ||
* @param buildState function that returns a state | ||
*/ | ||
export declare function makeStore<Id extends string, S extends StateTree, G extends Record<string, StoreGetter<S>>>(id: Id, buildState: () => S, getters?: G): { | ||
useStore: () => CombinedStore<Id, S, G>; | ||
clear: () => void; | ||
}; | ||
export {}; | ||
export { createStore } from './store'; |
{ | ||
"name": "pinia", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "Some awesome description", | ||
@@ -5,0 +5,0 @@ "main": "dist/pinia.common.js", |
231
README.md
@@ -1,11 +0,51 @@ | ||
# pinia [![Build Status](https://badgen.net/circleci/github/posva/pinia/master)](https://circleci.com/gh/posva/pinia) [![npm package](https://badgen.net/npm/v/pinia)](https://www.npmjs.com/package/pinia) [![coverage](https://badgen.net/codecov/c/github/posva/pinia/master)](https://codecov.io/github/posva/pinia) [![thanks](https://badgen.net/badge/thanks/♥/pink)](https://github.com/posva/thanks) | ||
# Pinia [![Build Status](https://badgen.net/circleci/github/posva/pinia/master)](https://circleci.com/gh/posva/pinia) [![npm package](https://badgen.net/npm/v/pinia)](https://www.npmjs.com/package/pinia) [![coverage](https://badgen.net/codecov/c/github/posva/pinia/master)](https://codecov.io/github/posva/pinia) [![thanks](https://badgen.net/badge/thanks/♥/pink)](https://github.com/posva/thanks) | ||
> Some awesome description | ||
> Pronounced like the fruit, in Spanish _Piña_ | ||
> | ||
> _Piña_ is also an invalid package name... | ||
🍍Type Safe Modular and lightweight (but **Experimental**) Store for Vue based on the composition api | ||
Demo (TODO link) | ||
⚠⚠⚠ This project is experimental, it's an exploration of whan a _Store_ could be like using [the composition api](https://vue-composition-api-rfc.netlify.com). It works for Vue 2 by using the [official library](https://github.com/vuejs/composition-api). | ||
What I want is to maybe inspire others to think about ways to improve Vuex. | ||
There are the core principles that I try to achieve with this experiment: | ||
- Flat modular structure 🍍 No nesting, only stores, compose them as needed | ||
- Light layer on top of Vue 💨 keep it under 1kg gzip | ||
- Only `state` and `getters` 👐 `patch` is the new _mutation_ | ||
- Actions are just functions ⚗️ Group your business there | ||
- import what you need, let webpack code split 📦 And you won't need modules! | ||
- SSR support ⚙️ | ||
- DevTools support 💻 Which is crucial to make this enjoyable | ||
## FAQ | ||
A few notes about the project and possible questions: | ||
**Q**: _Does this replace Vuex, is it its successor?_ | ||
**A**: No, or at least that's not the main intention | ||
**Q**: _What about dynamic modules?_ | ||
**A**: Dynamic modules are not type safe, so instead [we allow creating different stores](#composing-stores) that can be imported anywhere | ||
## Roadmap / Ideas | ||
- [ ] List Getters on DevTools | ||
- [ ] Nuxt Module | ||
- [ ] Automatic fresh store on Server Side? | ||
- [ ] Flag to remove devtools support (for very light production apps) | ||
- [ ] Allow grouping stores together into a similar structure and allow defining new getters | ||
## Installation | ||
```sh | ||
npm install lib-boilerplate | ||
yarn add pinia | ||
# or with npm | ||
npm install pinia | ||
``` | ||
@@ -15,4 +55,187 @@ | ||
## API | ||
### Creating a Store | ||
You can create as many stores as you want, and they should each exist in isolated files: | ||
```ts | ||
import { createStore } from 'pinia' | ||
export const useMainStore = createStore( | ||
// name of the store | ||
// it is used in devtools and allows restoring state | ||
'main', | ||
// a function that returns a fresh state | ||
() => ({ | ||
counter: 0, | ||
name: 'Eduardo', | ||
}), | ||
// optional getters | ||
{ | ||
doubleCount: state => state.counter * 2, | ||
} | ||
) | ||
``` | ||
`createStore` returns a function that has to be called to get access to the store: | ||
```ts | ||
import { useMainStore } from '@/stores/main' | ||
export default createComponent({ | ||
setup() { | ||
const main = useMainStore() | ||
return { | ||
// gives access to the whole store | ||
main, | ||
// gives access to the state | ||
state: main.state, | ||
// gives access to specific getter, | ||
} | ||
}, | ||
}) | ||
``` | ||
**There is one important rule for this to work**: the `useMainStore` (or any other _useStore_ function) must be called inside of deffered functions. This is to allow the Vue Composition API plugin to be installed. \*\*Never, ever call `useStore` like this: | ||
```ts | ||
import { useMainStore } from '@/stores/main' | ||
// ❌ Depending on where you do this it will fail | ||
// so just don't do it | ||
const main = useMainStore() | ||
export default createComponent({ | ||
setup() { | ||
return {} | ||
}, | ||
}) | ||
``` | ||
Once you have access to the store, you can access the `state` through `store.state` and any getter directly on the `store` itself as a _computed_ property (from `@vue/composition-api`) (meaning you need to use `.value` to read the actual value on the JavaScript but not in the template): | ||
```ts | ||
export default createComponent({ | ||
setup() { | ||
const main = useMainStore() | ||
const text = main.state.name | ||
const doubleCount = main.doubleCount.value // notice the `.value` at the end | ||
return {} | ||
}, | ||
}) | ||
``` | ||
`state` is the result of a `ref` while every getter is the result of a `computed`. Both from `@vue/composition-api`. | ||
### Mutating the `state` | ||
To mutate the state you can either directly change something: | ||
```ts | ||
main.state.counter++ | ||
``` | ||
or call the method `patch` that allows you apply multiple changes at the same time with a partial `state` object: | ||
```ts | ||
main.patch({ | ||
counter; -1, | ||
name: 'Abalam', | ||
}) | ||
``` | ||
The main difference here is that `patch` allows you to group multiple changes into one single entry in the devtools. | ||
### Replacing the `state` | ||
Simply set it to a new object; | ||
```ts | ||
main.state = { counter: 666, name: 'Paimon' } | ||
``` | ||
### SSR | ||
The main part about SSR is **not sharing `state`** between requests. So we can pass `true` to `useStore` **once** when getting a new request on the server. If we follow [the SSR guide](https://ssr.vuejs.org/guide/data.html), our `createApp` should look like this: | ||
```ts | ||
export function createApp() { | ||
// Here there could also be a router | ||
const store = useStore(true) | ||
// we can change the state now! | ||
store.state.counter++ | ||
// create the app instance | ||
const app = new Vue({ | ||
render: h => h(App), | ||
}) | ||
// expose the app and the store. | ||
return { app, store } | ||
} | ||
``` | ||
### Actions | ||
Actions are simply function that contain business logic. As with components, they **must call `useStore`** to retrieve the store: | ||
```ts | ||
export async function login(user, password) { | ||
const store = useUserStore() | ||
const userData = await apiLogin(user, password) | ||
store.patch({ | ||
name: user, | ||
...userData, | ||
}) | ||
} | ||
``` | ||
### Composing Stores | ||
Composing stores may look hard at first glance but there is only one rule to follow really: | ||
If **multiple stores use each other** or you need to use **multiple stores** at the same time, you must create a **separate file** where you import all of them. | ||
If one store uses an other store, there is no need to create a new file, you can directly import it. Think of it as nesting. | ||
#### Shared Getters | ||
If you need to compute a value based on the `state` and/or `getters` of multiple stores, you may be able to import all the stores but one into the remaining store, but depending on how your stores are used across your application, **this would hurt your code splitting** as you importing the store that imports all others stores, would result in **one single big chunk** with all of your stores. | ||
To prevent this, **we follow the rule above** and we create a new file: | ||
```ts | ||
import { computed } from '@vue/composition-api' | ||
import { useUserStore } from './user' | ||
import { useCartStore } from './cart' | ||
export const summary = computed(() => { | ||
const user = useUserStore() | ||
const cart = useCartStore() | ||
return `Hi ${user.state.name}, you have ${cart.state.list.length} items in your cart. It costs ${cart.price}.` | ||
}) | ||
``` | ||
#### Shared Actions | ||
When an actions needs to use multiple stores, we do the same, we create a new file: | ||
```ts | ||
import { useUserStore } from './user' | ||
import { useCartStore, emptyCart } from './cart' | ||
export async function orderCart() { | ||
const user = useUserStore() | ||
const cart = useCartStore() | ||
try { | ||
await apiOrderCart(user.state.token, cart.state.items) | ||
emptyCart() | ||
} catch (err) { | ||
displayError(err) | ||
} | ||
} | ||
``` | ||
## Related | ||
@@ -19,0 +242,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
43420
12
245
0
739