Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: Comparison of Actions to Mutations is misleading #915

Open
davestewart opened this Issue Aug 22, 2017 · 5 comments

Comments

Projects
None yet
4 participants
@davestewart
Copy link
Contributor

davestewart commented Aug 22, 2017

What problem does this feature solve?

I note the introduction text on the Vuex docs for Actions:

Actions

Actions are similar to mutations, the differences being that:

  • Instead of mutating the state, actions commit mutations.
  • Actions can contain arbitrary asynchronous operations.

Let's register a simple action:

This sets up in the readers mind that Actions are somehow the same as Mutations, when in fact their differences are more pronounced than their similarities:

  • Actions don't update the state, but they may commit() mutations, which do (there is no "instead of")
  • Mutations must be synchronous, there is no such restriction on Actions
  • Mutations generally won't make other calls, Actions probably will
  • Mutations must return a new state object, Actions don't need to return anything
  • Mutations must not have side effects, whereas Actions could (changing a route, perhaps)

What does the proposed API look like?

Perhaps something like the following would be more appropriate:

Actions provide a mechanism to run additional logic or functionality within the context of the current store or store module.

A typical use case would be to collate and submit data to the server, committing mutations only when the remote call completes.

Actions are declared as JavaScript callbacks, taking a special context object as their first argument, with additional user-supplied parameters passed after.

The context object is the primary way to access to local and root-level state and getters, along with localised commit and dispatch functions, and may be expanded to local variables using ES6 destructuring:

[ action example that demonstrates the above ]

@posva

This comment has been minimized.

Copy link
Member

posva commented Aug 22, 2017

I like the A typical use case would be to collate and submit data to the server, committing mutations only when the remote call completes. but, they're similar in roles and I think it helps for most people. You seem to have a very technical point of view, but that's not the case for everybody. Some people will understand it better with the similar to sentence

@posva posva added the docs label Aug 22, 2017

@davestewart

This comment has been minimized.

Copy link
Contributor Author

davestewart commented Aug 23, 2017

You seem to have a very technical point of view

Does one not need to? Vuex is somewhat technical!

Some people will understand it better with the "similar to" sentence

I have to respect that point of view, but I think the current text implies correlation i.e. 1:1, when the relationship is actually causation, i.e. 1 → 2.

Using the initial intro paragraph, and the example you like, perhaps something like this:

Actions allow you to wrap logic, often asynchronous logic, around commits.

A typical use case would be to collate and submit data to the server, committing mutations only when the remote call completes.

You could then show the simple example, which I think still works, or perhaps expand the example with actual async logic:

// store definition
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    update (state, value) {
      state.count = value
    }
  },
  actions: {
    update (context, value) {
      axios
        .post('/update', value)
        .then(res => {
          context.commit('update', res.data.value)
        })
    }
  }
})
// usage
store.dispatch('update', 10)
@balint42

This comment has been minimized.

Copy link

balint42 commented Sep 2, 2017

I would like to make a slightly related comment - it concerns the exact same documentation chapter: reading through it I was left with the impression that actions may return Promises, not that they always by definition do. Quote:

store.dispatch can handle Promise returned by the triggered action handler and it also returns Promise:

This sentence is not exactly wrong but it does imho not make very clear that store.dispatch will always return a Promise no matter what the action returns. What about:

"store.dispatch will always return a Promise and thus can handle Promises returned by the triggered action handler."

@davestewart

This comment has been minimized.

Copy link
Contributor Author

davestewart commented Sep 3, 2017

@balint42 - I completely agree with you - the word "may" is ambiguous in documentation!

The Laravel docs use "may" all over the place, I think to sound polite, it's not explicit whether a result will be of yours or the framework's making.

As an end user you just want to know in concrete terms whether something "is" or "isn't".

@davidpelayo

This comment has been minimized.

Copy link

davidpelayo commented Apr 25, 2018

When it comes to how commit and dispatch works - I think the terms are ambiguous too.
Inspecting the code and how actions are dispatched, they are by default synchronous unless the action returns a Promise.

So, given the following action:

updateConfig({ commit }, someConfigObject) {
  commit('CONFIG', someConfigObject);
},

That gets executed synchronously, as if you check the code here, the action doesn't return a Promise, there is no async operation by default.

Could we improve the docs so we make that much clearer? Happy to raise a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.