Oh, ok. I have code in my event handler that computes a value from the db and then the event handler computes an effect from that value. I was trying to move the code that computes the value out of that function. Something like on-changes
but in the :before position instead of :after. I’m just not sure how to refactor my code and I thought I’d try interceptors.
Sounds like you can simply compute that within the event handler itself, no?
The concrete problem in the scenario above is that db-handler->interceptor
is a :before
interceptor and path
is both :before
and :after
. So path
changes the :db
effect in its :after
phase.
Yes, I can. I think the first thing that made me unhappy is seeing re-frame docs https://day8.github.io/re-frame/correcting-a-wrong/#a-final-faq criticizing hard coding db paths. In the view, I enjoy subscribing to data that doesn’t really exist in the db but is computed from the db. I was trying to put those two ideas together.
Right. I do want to get {:db {:p {:a {:th 1}}}}
out of it. I was surprised that I got the same result in both orderings. I don’t expect it to work with the handler interceptor first. The handler :before should run and following that the path’s :before and :after, right?
I was motivated to post here because I see my understanding is wrong regarding how it works. I actually have the result I was trying to get…
Thanks for taking the time. brb
That particular FAQ entry criticizes not hardcoding db paths but using db paths in your views. That's completely different.
Two :before
interceptors will run according to the order of the interceptors.
Two :after
interceptors will run in the reverse order.
Any :before
always runs before any :after
.
There was some nice pic in the documentation about it, IIRC.
When in doubt, just read through re-frame source code (after you're done with the documentation, if you aren't that comfortable with reading code written by somebody else) - it's not that large, especially the relevant parts, and most of it is docstrings anyway. The most complex part is event queue IMO, and you don't need that part at all.
I did read through the source before coming up with my example. I think I understand it pretty well. In the first expression where the interceptor list has the handler followed by the path, I expect the handler :before to happen before the path :before. Then I would see the handler assoc :th under :db and not the path.
Hey.
Is there a best practice way to inject the js/document
into a reg-sub
using interceptors?
My reframe subscription calculates the position of elements in a game board div in relation to each other. Using getElementById js/document
and the .-offsetLeft
to calculate css left and top would make the sub non pure. I could also do the positional math in the component directly.
Interceptors are only for events, not subscriptions.
No need to inject js/document
anywhere because it's already a singleton. Unless you need to create mocks of documents.
Even if you use js/document
in a sub, the sub won't be recalculated because a document has nothing to do with the Reagent's reactive context.
Don't use getElementById
if you are the one controlling that component. Instead, use React refs.
There are two reasonable ways to solve that:
- Listen to some JS event that's fired when that position that you're interested in changes. If there are no such events, just do it on each requestAnimationFrame
. In the JS event listener dispatch
a re-frame event and write the position to the re-frame's app-db
. In the relevant sub, just use that position
- Don't use re-frame for that particular part of your app - just keep it confined to Reagent. But it's a trade-off
Ah thanks. Thought subs should be pure. My board cells don’t change. their offset is the reference point for tokens to move around. Would you still use react ref for it?