How to fetch relationships of an item and update the store?
pharkasbence opened this issue · comments
If I use the getRelated action, it fetches the relationships but it doesn't update the relationships of the base item in the store. Is there a way to do that without fetch the base item with includes?
At the moment updates to items in the store only happen when the item itself changes - so references are put in pointing from an item to it's related items, but the related items are not updated to reflect the relationship in the opposite direction. It's actually a hard problem to solve, and is discussed in #87 .
There are still some options though. getRelated
currently looks to see if the item it's being passed as an argument is in the store, and has a _jv/relationships
section. If it does, then this is used to look up the related items - if not then the item is fetched and then relationships followed.
This means that you can clear the item (or it's relationships) out of the store before calling getRelated
, and it will be fetched 'fresh' before fetching the related items. The easiest option is probably just to use the deleteRecord
mutation just before the dispatch.
It would actually be trivial for me to add a config option that makes getRelated
always refresh the item. Let me know if the above solves your issue, and if it does I'll add this as a new feature.
If I clear the item out of the store before calling getRelated
, then it doesn't fetch the item itself, it fetches only its relationships. I use it this way:
this.$store.commit('jv/deleteRecord', { _jv: { type: 'my-type', id: <id> } })
this.$store.dispatch('jv/getRelated', 'my-type/<id>/<relationshipName>')
Apologies - I was talking nonsense before, as I was going from memory, not from the actual code!
It appears that the code never looks at the store at all. It just looks at the argument to getRelated
- if it's an object containing _jv/relationships
it uses that 'direct' - otherwise it fetches the object from the store and then follows it's relationships.
Since the get from the store uses the get
action internally, this should also update the store as it goes... so I'm confused what's happening.
Can you confirm that for you, doing:
this.$store.dispatch('jv/getRelated', 'my-type/<id>')
Doesn't create/update the item in the store? If so then this is a bug that needs investigating.
It does create/update the item in the store, but this doesn't:
this.$store.dispatch('jv/getRelated', 'my-type/<id>/<relationshipName>')
Ahh, I see why this happens - the code is actually leveraging some of the JSONAPI standard, which I had forgotten about, using the related
link: https://jsonapi.org/format/#fetching
If you pass the argument my-type/<id>/<relationshipName>
then actually the api GET fetches the related item directly, e.g. /my-type/1/myRelationship
so yes the original item won't be fetched.
So as it stands there are several pathways through this code, depending on the argument:
my-type/1
- fetches the original item, checks rels, then fetches them._jv: { type: 'my-type', id: '1' }
- As abovemy-type/1/relName
- fetchesrelName
directly - doesn't fetch original item._jv: { type: 'my-type', id: '1', relationships: { relName {...}}}
- As above (different codepath but same effect).
The end result is that the code assumes that if you are specifying the relationship(s) you want to fetch, that you trust the store is up-to-date, and you don't need it to fetch the original item before the relationships.
Now, in terms of solving your original question... 😀
I think you have 2 choices:
-
Stop adding the relationship to the query - that will force the call to get the original object and it's relationships. However there's an inefficiency in that all relationships will be updated, which you might not care about.
-
Explicitly call
get
prior to callinggetRelated
. You don't need to wait for theget
to complete so they can be fired off without usingawait
orthen
. If you do this often it would be easy to create a wrapper that does this for you (it's easy enough to split the arg to get the item endpoint out).
Let me know what you think! I'm happy enough to make changes to the code - I just can't immediately see a nice way to change things here...
Thank you for your answer, I'd prefer the first choice :)
Great - if you're ok with this solution then please close this call 😃