So in that example query the :comment/reply
would also have all the same attributes as a :comment/by-id
?
@sova yes, correct
also, if your parser is being called, the query
will be just that, the same attributes, it kind makes the implementation go automatically for it
@wilkerlucio Wow! Great article!
I'm at a loss how to re-run a query after a remote mutation.
I had the idea for my backend to return {:reads! [:some/read]}
and I would detect this special :reads!
key in my merge function and call (transact! reconciler reads)
but it doesn't really work because it's actually a specific join query I want to re-run, not the bare key.
I don't really understand how to integrate novelty into the state after a remote mutation, it seems the query passed to merge is useless for this.
thank you @thosmos ๐
@danielstockton it's part of Om.next design for the UI (the transaction caller) to be responsible about doing that, can feel weird at first, but try it, usually it's not that much to keep that responsability there
Trouble is, I'm not sure how. Merge seems to be the only place where I can do something after a remote response.
If I pass reads to the transaction caller, they'll happen too early.
Won't they?
I tried it, they get fired immediately (which means if it's a remote call, it is sent in the same request as the mutation itself).
Not sure about the indexer indexing transacts but the indexer will update components that have queries reading keys that are merged in, or keys returned by :keys from merge.
It doesn't wait for the remote call, it will fire the reads immediately.
hum, you are using Om.next pure? or with some framework on top of it?
Om.next pure on the client side, custom parser (python django) on the back.
got it, so, on this case I don't know much =/
if you use Untangled it actually waits for it, and otherwise there is the after-mutation
things you can do
Yeah, I wonder how that mechanism works.
but Untangled does a different process, using 2 reconcilers for it
it triggers remotes on a secondary reconciler, that's more managed and controlled, this contrasts with Om.next pure approach that asks for remote whenever it tries to fetch something not present on local state
in Untangled this is explicit instead of implicit
but they are just different approaches, I'm sure it must be a way to handle this on Om.next pure too
I was thinking to pass the query/component as parameters to the mutation, just to have them available in merge.
That way, the transactor could control what is re-read rather than the server and I can pass through the complete query rather than just a key.
try it, and please let us know if it worked ๐
Did you learn about the 2 reconcilers untangled uses from reading the source or is this documented?
I used to pass a "mutation-uuid" parameter with each mutation, so I could identify it later.
But it got tedious to sprinkle the uuid with every mutation. Now instead I've wrapped my mutate with a function that takes the uuid generated with om/transact!
and puts it in my mutation's parameters (by modifying the ast).
I can parse the mutation's uuid in send
and pass it to merge
This sounds similar to what I had in mind:
(om/transact this `[(some/mutation {:param1 "a parameter" :reads! [{:some/read ~(om/get-query SubComponent)}])
and then read the query/ast in merge.Maybe I missed it, but what's the problem with passing the reads after the mutation?, i.e:
(om/transact this `[(some/mutation {:param1 "a parameter"}) {:some/read ~(om/get-query SubComponent)}]
Is it because :some/read
is not a remote read, and the return value of the remote mutation changes the outcome of a local :some/read
?I've structured my reads/mutations such that I don't rely on what's returned by mutations. Just sending [(some/mutation {})]
wouldn't do anything to my app-state
The benefit of this is that I always send my reads, which I can return from merge and om.next will update the components that care
But yeah, if you want to do something after a mutation in merge, passing it as parameters seems like it would work
"Is it because :some/read
is not a remote read, and the return value of the remote mutation changes the outcome of a local :some/read
?" - It's because it changes the outcome of a remote read so i want to re-read that after the remote mutation.
Specifically, I'm adding a new item to a list (on the server) and my UI needs to re-read the list. It's not possible to optimistically update the list on the client side, I need things only the server can provide.
I hear Tony Kay talking about it somewhere
Ok, then I'm confused. Wouldn't specifying the read after the mutation execute the read just like your saying? In my mind it would read 3 times: optimistic client-side -> after mutation server-side -> post remote mutation client-side (triggered by merge returning {:keys [:some/read] ...}
)
@peeja found your figwheel reload gist for reloading components without remounting the root component. https://gist.github.com/Peeja/eccd5e8169709c12ec0420c86beb49b9 we actually do want to update local state. Do you know a way to do that?
@petterik If I specify the read as a trailing arg to transact, it actually gets sent in the same request as the mutation. Interestingly, this seems to work, but I'm not sure if I can rely on that behaviour. It depends which is parsed first.
Sending the reads as params on the mutation also worked (FYI) when I transacted them in merge.
I think I can rely on the order actually, it's a vector after all.
It's optimistic client-side -> after mutation server-side
... guess i'm missing something for post remote mutation client-side, or that isn't the case.
My merge function is a thin wrapper over default-merge, I just pull out some error keys and have special behaviour when a user is returned (login/logout).
@danielstockton Does your merge function return :keys
to re-read? The keys returned from merge is queued:
https://github.com/omcljs/om/blob/master/src/main/om/next.cljc#L2330-L2332
Yeah, I checked the source. It looks like default-merge takes the keys from the response, so no, I'm not in the case of mutations.
ok
I actually think it's fine with just optimistic client-side
and after mutation server-side
, don't think I need the after mutation client-side
.
@denik I'm not sure I follow. What do you want to do?
@peeja figure out whether a componentโs local state has changed and remount it
What would change the local state?
If you change the local state of a component, the component should re-render with the new state automatically. It knows to do that because it's managing its own state, and you just told it to change that state.
If that's not what you're seeing, there may be a deeper issue
Question: It looks to me like the indexer indexes component classes by keys (`:prop->classes`) and component instances by ref (`:ref->components`). If a component instance changes its query to use different keys, does the indexer not pay attention? If a merge changes one of the keys in that new query, will the component instance be re-rendered or not?
have you actually tried it? It's been a while since I did this, but my memory is that by adding the read key to the transact!, it adds that key to the indexer, so when that key later gets merged, it updates all components that have transact!s with reads on that key ... I might be wrong, so you should test it