Updated MPJ browser state draft

This commit is contained in:
Daniel J. Summers 2018-08-25 10:04:04 -05:00
parent 6e8ba49834
commit be00a9cb6d

View File

@ -42,19 +42,21 @@ _(Side note: although these functions are called "mutations," Vuex is actually r
So, what do you do when you need to run an asynchronous process - like, say, calling an API to get the requests for the journal? These processes are called actions, and are defined on the `actions` property of the store. Actions receive an object that has the state, but it also has a `commit` property that can be used to commit mutations.
If you look at [line 87 of store/index.js][line87], you'll see the above concepts put into action<a href="#note-1"><sup>1</sup></a> as a user's journal is loaded. This one action can commit up to 4 mutations of state. The first clears out whatever was in the journal before, commits the `LOADED_JOURNAL` mutation with an empty object. The second sets the `isLoadingJournal` property to `true` via the `LOADING_JOURNAL` mutation. The third, called if the API call resolves successfully, commits the `LOADED_JOURNAL` mutation with the results. The fourth, called whether it works or not, commits `LOADING_JOURNAL` again, this time with `false` as the parameter.
If you look at [line 87 of store/index.js][line87], you'll see the above concepts put into action<a href="#note-1"><sup>1</sup></a> as a user's journal is loaded. This one action can commit up to 4 mutations of state. The first clears out whatever was in the journal before, committing the `LOADED_JOURNAL` mutation with an empty object. The second sets the `isLoadingJournal` property to `true` via the `LOADING_JOURNAL` mutation. The third, called if the API call resolves successfully, commits the `LOADED_JOURNAL` mutation with the results. The fourth, called whether it works or not, commits `LOADING_JOURNAL` again, this time with `false` as the parameter.
A note about the names of our mutations and actions - the Vuex team recommends defining constants for mutations and actions, to ensure that they are defined the same way in both the store, and in the code that's calling it. This code follows their recommendations, and those are defined in `action-types.js` and `mutation-types.js` in the `store` directory.
## Using the Store
So, we have this nice data store with a finite number of ways it can be mutated, but we have yet to use it. Since we looked at loading the journal, let's use it as our example ([mpj:Journal.vue][Journal.vue]). Beginning on line 49, we wrap up the computed properties with `...mapState`, which exposes data items from the store as properties on the component. Just below that, the `created` function calls into the store, exposed as `$store` on the component instance, to execute the `LOAD_JOURNAL` action.
So, we have this nice data store with a finite number of ways it can be mutated, but we have yet to use it. Since we looked at loading the journal, let's use it as our example ([mpj:Journal.vue][Journal.vue]). On line 56, we wrap up the computed properties with `...mapState`, which exposes data items from the store as properties on the component. Just below that, the `created` function calls into the store, exposed as `$store` on the component instance, to execute the `LOAD_JOURNAL` action.
The template uses the mapped state properties to control the display. On lines 4 and 5, we display one thing if the `isLoadingJournal` property is true, and another (which is really the rest of the template) if it is not. Line 12 uses the `journal` property to display a `RequestCard` ([mpj:RequestCard.vue][RequestCard.vue]) for each request in the journal.
I mentioned developer sanity above, and in the last post, I said that the logic that has `RequestCard` making the decision on whether it should show, instead of `Journal` deciding which ones it should show, would make sense. This is where we put those pieces together. The Vuex store is reactive; when data from it is rendered into the app, Vue will update the rendering if the store is changed. So, `Journal` simply displays a "hang on" note when the journal is loading, and "all the requests" once it's loaded. `RequestCard` only displays if the request should be displayed. And, the entire "brains" behind this is the thing that starts the entire process, the call to the `LOAD_JOURNAL` action. We aren't moving things around, we're simply displaying the state of things as they are!
I mentioned developer sanity above; and in the [last post][part1], I said that the logic that has `RequestCard` making the decision on whether it should show, instead of `Journal` deciding which ones it should show, would make sense. This is where we put those pieces together. The Vuex store is reactive; when data from it is rendered into the app, Vue will update the rendering if the store changes. So, `Journal` simply displays a "hang on" note when the journal is loading, and "all the requests" once it's loaded. `RequestCard` only displays if the request should be displayed. And, the entire "brains" behind this is the thing that starts the entire process, the call to the `LOAD_JOURNAL` action. We aren't moving things around, we're simply displaying the state of things as they are!
`RequestListItem` ([mpj:RequestListItem.vue][RLI.vue]) is another component that bases its display off state. It will always provide a button to view the full request, but based on whether the request is answered, snoozed, or in a recurrence period, it will display the appropriate buttons and informational text. It is used by the `ActiveRequests`, `SnoozedRequests`, and `AnsweredRequests` list components, and those components are very simple; `ActiveRequests` and `SnoozedRequests` simply operate on the already-loaded journal, while `AnsweredRequests` pulls its data when the page is loaded.
`Navigation` ([mpj:Navigation.vue][Navigation.vue]) is another component that bases its display off state, and takes advantage of the state's reactivity. By mapping `isAuthenticated`, many of the menu items can be shown or hidden based on whether a user is signed in or not. Through mapping `journal` and the computed property `hasSnoozed`, the "Snoozed" menu link does not show if there are no snoozed requests; however, the first time a request from the journal is snoozed, this one appears _**just because the state changed**_.
This is one of the things that cemented the decision to use Vue for the front end<a href="#note-2"><sup>2</sup></a>, and is one of my favorite features of the entire application. _(You've probably picked up on that already, though.)_
<p>&nbsp;</p>
@ -63,10 +65,14 @@ We've now toured our stateful front end; next time, we'll take a look at the API
---
<a name="note-1"><sup>1</sup></a> _Pun not originally intended, but it is now!_
<a name="note-2"><sup>2</sup></a> _The others were the lack of ceremony and the Single File Component structure; both of those seem quite intuitive._
[intro]: /2018/a-tour-of-myprayerjournal/introduction.html "A Tour of myPrayerJournal: Introduction | The Bit Badger Blog"
[Vuex]: https://vuex.vuejs.org
[store]: https://github.com/bit-badger/myPrayerJournal/blob/1.0.0/src/app/src/store/index.js "app/src/store/index.js | myPrayerJournal | GitHub"
[line87]: https://github.com/bit-badger/myPrayerJournal/blob/1.0.0/src/app/src/store/index.js#L87 "app/src/store/index.js (line 87) | myPrayerJournal | GitHub"
[Journal.vue]: https://github.com/bit-badger/myPrayerJournal/blob/1.0.0/src/app/src/components/Journal.vue "app/src/components/Journal.vue | myPrayerJournal | GitHub"
[RequestCard.vue]: https://github.com/bit-badger/myPrayerJournal/blob/1.0.0/src/app/src/components/request/RequestCard.vue "app/src/components/request/RequestCard.vue | myPrayerJournal | GitHub"
[RLI.vue]: https://github.com/bit-badger/myPrayerJournal/blob/1.0.0/src/app/src/components/request/RequestListItem.vue "app/src/components/request/RequestListItem.vue | myPrayerJournal | GitHub"
[part1]: /2018/a-tour-of-myprayerjournal/the-front-end.html#Components "Components | A Tour of myPrayerJournal: The Front End | The Bit Badger Blog"
[Navigation.vue]: https://github.com/bit-badger/myPrayerJournal/blob/1.0.0/src/app/src/components/common/Navigation.vue "app/src/components/common/Navigation.vue | myPrayerJournal | GitHub"