Skip to content

Commit 9696be4

Browse files
Update store-pattern.md
1 parent 87e0c37 commit 9696be4

File tree

1 file changed

+106
-10
lines changed

1 file changed

+106
-10
lines changed

recipes/javascript/packages/vue/state-management/store-pattern.md

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,70 @@ You don't need a library like Vuex here - for simple cases you can implement you
77

88
{% raw %}
99

10-
## Resources
1110

12-
The example below is based on [Simple State Management from Scratch](https://v3.vuejs.org/guide/state-management.html#simple-state-management-from-scratch) in the Vue 3 docs.
11+
## Store in state variable
1312

14-
> ... if you have a piece of state that should be shared by multiple instances, you can use a reactive method to make an object reactive
13+
This value will persist when switching views, that is it. The value will get lost if you do anything else. See [Persist in storage](#persist-in-storage) below for alternate approach.
1514

16-
See also the [reactive](https://v3.vuejs.org/guide/reactivity-fundamentals.html) Vue method in the docs, as that is used below.
15+
### Repo username
1716

17+
Here a form is used to enter a username of a repo. This is stored in the state and accessed on multiple views.
1818

19-
## Persist
19+
- `src/store.js`
20+
```javascript
21+
const DEFAULT_USERNAME = "MichaelCurrin"
22+
23+
const store = {
24+
debug: true,
2025

21-
If you want to persist values when revisiting the site, you can use local storage.
26+
state: reactive({
27+
repoUsername: DEFAULT_USERNAME,
28+
}),
2229

23-
Then instead of getting and setting on `this.state`, you could use `localStorage`. And using the store pattern, the rest of the app won't care how it's stored and will just have to interact with the store wrapper.
30+
setRepoUsername(value: string) {
31+
if (this.debug) {
32+
console.debug(`Storing repo username: ${value}`);
33+
}
2434

25-
## Example
35+
this.state.repoUsername = value;
36+
},
37+
};
2638

27-
- `store.js` - store in JavaScript. Set up a store object with a debug attribute, a state attribute with our data in it, and some methods that are used to set data on the state.
39+
export default store;
40+
```
41+
- `MyVue.vue` - some page on the site. Read a value using by getting it from `state` on the `store`. Or you could make and use `getRepoUsername` instead.
42+
```vue
43+
<script>
44+
import store from "@/store";
45+
46+
export default {
47+
data() {
48+
return {
49+
username: store.state.repoUsername,
50+
},
51+
},
52+
methods: {
53+
submit() {
54+
store.setRepoUsername(this.username);
55+
}
56+
}
57+
}
58+
</script>
59+
```
60+
61+
From my testing, if you only have on App instance then you can leave out reactive:
62+
63+
```javascript
64+
const store = {
65+
state: {
66+
repoUsername: DEFAULT_USERNAME,
67+
},
68+
}
69+
```
70+
71+
### Message
72+
73+
- `src/store.js` - Set up a store object with a debug attribute and a state attribute with our data in it. Plus some methods that are used to set data on the state.
2874
```javascript
2975
import { reactive } from 'vue'
3076
@@ -54,7 +100,7 @@ Then instead of getting and setting on `this.state`, you could use `localStorage
54100
55101
export default store
56102
```
57-
- `App.vue` - Vue file. Set up app using the store. Here we have two App components using the same store and mount them on different elements. These could be on the same or different pages.
103+
- `App.vue` - Vue file. Set up app using the store. For demostration, here we actually have two App components using the same store and mount them on different elements. These could be on the same or different pages.
58104
```javascript
59105
import { createApp } from "vue"
60106
import store from "./store.js"
@@ -93,4 +139,54 @@ Then instead of getting and setting on `this.state`, you could use `localStorage
93139
</div>
94140
```
95141

142+
143+
## Persist in storage
144+
145+
Here we store a value in local storage. This has the following benefits:
146+
147+
- Persist across page views (navigating)
148+
- Persist across reloading the page or closing and opening the browser
149+
- State is available across tabs and windows for the current browser, though only for the current domain.
150+
151+
Then instead of getting and setting on `this.state`, you could use `localStorage`. And using the store pattern, the rest of the app won't care how it's stored and will just have to interact with the store wrapper.
152+
153+
### Repo username
154+
155+
I found that when using a `state` attribute on `store`, there would be a lag that means that the value is not used when switching views.
156+
157+
Even when using `reactive`:
158+
159+
```javascript
160+
const store = {
161+
state: reactive({
162+
repoUsername: localStorage.getItem("repoUsername")
163+
}),
164+
165+
// setRepoUsername...
166+
```
167+
168+
So I left out `state` completely and that works. It was also suggested on this [thread](https://stackoverflow.com/questions/51015101/how-to-make-data-from-localstorage-reactive-in-vue-js) to no try and make it reactive. I guess because Vue can't check when the value is updated - the value is only known when doing a `getItem` call.
169+
170+
```javascript
171+
const store = {
172+
getRepoUsername() {
173+
return localStorage.getItem('repoUsername')
174+
},
175+
176+
/**
177+
* Store a repository username. e.g. 'MyUsername'.
178+
*/
179+
setRepoUsername(value: string) {
180+
if (this.debug) {
181+
console.debug(`Storing repo username: ${value}`);
182+
}
183+
184+
localStorage.setItem('repoUsername', value)
185+
},
186+
```
187+
188+
### TodoMVC
189+
190+
See also the [TodoMVC](https://v3.vuejs.org/examples/todomvc.html) example in the docs, which uses `localStorage`.
191+
96192
{% endraw %}

0 commit comments

Comments
 (0)