mrichar1 / jsonapi-vuex

Use a JSONAPI api with a Vuex store, with data restructuring/normalization.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

I don't understand dispatch

geoidesic opened this issue · comments

I've read through this like 20 times but I still don't understand it: https://github.com/mrichar1/jsonapi-vuex#restful-actions

So confused. So let me highlight all the bits that confuse me.

  1. First it says that dispatch takes 2 arguments and that the first argument should be an object containing restructured data (whatever that means)... but then in every example shown, the first argument is a string, not an object.

  2. Then it says that the dispatch action only takes a single argument... but then in every dispatch example shown it takes 2 arguments.

  3. This sentence makes no sense at all to me, may as well be greek: "The first argument is an object containing restructured data. Actions which take no data argument apart from the record (get and delete) can also accept a URL to fetch (relative to axios baseURL (if set) leading slash is optional). This means you don't need to create an 'empty' restructured data object to get or delete a record." Seriously anytime one has (parenthesis (within parenthesis)), in written English, one could probably simplify the message.

  4. The structure of an actual post message isn't clear from the examples. E.g. ".dispatch('jv/post', [newWidget, { params: params }])"... so does that mean that my data would be like this: .dispatch('jv/post', [newWidget, { params: {data: {} }]) or like this: .dispatch('jv/post', [newWidget, { data: {} }]) or something else? [UPDATE: the answer to this is that newWidget is the data payload object, not sure what params is, presumably an axios config object]

  5. In the first paragraph it mentions that one of the arguments is an optional axios config object... is that the same thing as {params: params}?

  6. Oh and then sometimes the second argument is an array, which seems to repeat part of the first argument. Not sure what to make of that.

[UPDATE]: looking at the the examples folder in the codebase it demonstrates manually setting _jv on the payload:

postWidget: {
        _jv: {
          type: 'widget',
        },
      },
  1. Is this necessary? Seems clunky; shouldn't the _jv store already know what type it is by default?
  2. Also what is type? Is it the name of the vuexstore, or the api endpoint string?

Ok, so I eventually managed to get it to save. The key was that the payload has to have the _jv node with the type defined. I'm still not sure whether type is the name of the vuexstore or the endpoint but in this case both are the same so it's immaterial. All the key-value pairs that are being saved have to be at the same level as the _jv node. E.g.

const data = {
_jv: { type: 'clients'},
firstname: 'John',
surname: 'Malkovich'
}

And you send it like so: store.dispatch('clients/post', data)

This works (i.e. saves my data to my JSONAPI backend correctly). However it also produces a swarm of errors in the console (see screenshot):
Screenshot 2019-11-22 at 23 27 19

Hi - there's a lot to answer in this issue, so I'll start with a high-level overview, and then drill down if there are any bits which that doesn't explain.

1/2. Dispatch arguments:

I think the confusion comes about from the fact that in Vuex terms, dispatch takes 2 parameters - the first is the name of the action(e.g. jv/get), the second is the argument passed to the action. The docs only refer to this 2nd parameter.

Hopefully with that in min the docs become much clearer. I can add an extra note to the start of the section explaining this difference if you think it helps?

The first argument can be either a string (path) or an object. It happens that the examples only show strings for getand object examples for post/patch but this is purely down to convenience

  1. Yes, the brackets are messy, it should probably read "Actions which take no data argument apart from the record (get and delete) can also accept a URL to fetch, relative to axios baseURL (if set). The leading slash is optional.

4/5. The docs are quite clear (albeit if you have understood what the action arguments are, as per 1.) The first argument references the item in the API (URL string or object), the 2nd is an axios config object. params is the most commonly used key in an axios config object, hence the example setting a token.

  1. See 1

7/8. type/_jv

Type is one of the mandatory fields in a JSONAPI record - see https://jsonapi.org/format/#document-resource-objects.

However... endpoints do not have to correspond to type in the JSONAPI spec. e.g. you can have an endpoint called people that returns person records. This means it can't be 'guessed' and must be set for new records.

However existing records will have type set so you can do things like using an item from the store, or the results of a get as the data for a patch.

Ok thank you for the detailed response!

Any idea why I'm getting these errors though (the screenshot above)?

I think it may be related to this code:

Object.keys(data).forEach(async key => {
  let clone = utils.deepCopy(data[key]);
  await db.instance.put(storeName, {
    ...utils.normToJsonapi(clone).data
  });
});

That code is operating on data that looks like this:
Screenshot 2019-11-23 at 21 56 43

... and producing these errors
Screenshot 2019-11-23 at 21 57 59

Great!

I'm not sure exactly where those errors are coming from... There are very few uses of in in the codebase, and none of them use it to search for _jv. Can you confirm that you are using the latest version of the project (3.2.2)? It's also worth looking at the value of data[key] to check that it's the correct format for passing to deepCopy and normToJsonapi (and try just one or the other to see which one each error relates to).

I can't recall how I solved these errors now but it was not an issue with this library.