Fork me on GitHub
David Pham04:05:24

What if you make the GMAP atom outside of the component? Or create an fx for it?

Harish Tella04:05:38

I was thinking of this ideo too. I could store the Google maps object in the reframe-db when the component initializes. And when the time comes to call a function on this object, I could call a re-frame effect that essentially grabs the object from the reframe-db and calls the function on it. The only thing that stopped me was that it seemed not re-framey. It seemed like I was mutating this component through a back-door kind of approach, and the proper front-door approach was through the component’s props.

David Pham12:05:15

Fx are for side effects so kind of okay right?

Harish Tella14:05:49

True, but the docs,, give examples of calling methods on databases or calling browser APIs, not calling a functions on some js-object within a reagent component. But in the end this could be the best approach.


is it possible to dispatch multiple events when using reg-event-fx? like so:

{:dispatch [:event-foo p1 p2 :event-bar p3 p4}


how does the order in which the events are dispatched work?


is the order undefined or does the order depend on the order of events listed?


I think the remark on that page is outdated. AFAIK the order is undefined.


So if you need strict sequentiality you're better off dispatching the second event at the end of the first handler.


See @U0JEFEZH6 answer on the channel... in the source code, the note on the order was removed


@U06B3TL74 I'm trying to set a Stripe token like so in an event-fx:

(.then (.createToken stripe card-element)
                 (fn [result]
                   (prn "result is" result)))
But I'm getting the error:
router.cljc:204 Uncaught Error: [object Promise] is not ISeqable
    at Object.cljs$core$seq [as seq] (core.cljs:1226)
    at re_frame$fx$do_fx_after (fx.cljc:74)
    at Object.re_frame$interceptor$invoke_interceptor_fn [as invoke_interceptor_fn] (interceptor.cljc:71)
    at Object.re_frame$interceptor$invoke_interceptors [as invoke_interceptors] (interceptor.cljc:109)
    at Object.re_frame$interceptor$execute [as execute] (interceptor.cljc:204)
    at Object.re_frame$events$handle [as handle] (events.cljc:65)
    at Object.eval [as re_frame$router$IEventQueue$_process_1st_event_in_queue$arity$1] (router.cljc:179)
    at Object.eval [as re_frame$router$IEventQueue$_run_queue$arity$1] (router.cljc:198)
    at eval (router.cljc:146)
    at Object.eval [as re_frame$router$IEventQueue$_fsm_trigger$arity$3] (router.cljc:169)
why might this be?



(let [stripe (js/Stripe. "foobar")
      elements (.elements stripe)
      card-element (.create elements "card" some-style)] ...)


Looks like you're trying to return a promise from the event handler. At least that's what I think the error means.


On the one hand this is not allowed as you should return a map of effects. And on the other hand, you should keep your event handlers side-effect free and use effects (registered with reg-fx) instead.


I'm not familiar with the Stripe API, but I assume .createToken there has a side effect. You should register that functionality in a re-frame effect which can be triggered from the event handler.


yeah, how would I return a map if I'm using (.then ..) ? I feel that I would need to make it impure and use (dispatch ...) instead inside of the (.then ...)?


Ultimately, I want to return a map {:db (assoc db :stripe-token (.-token result))}


Right. But obtaining that token is an effect.


Try something like this:


(reg-fx ::create-stripe-token
  (fn [params]
    (.then (.createToken stripe params)
      (fn [result] (dispatch [::token-created result])))))


Then you need a handler to save the token, ::token-created which will just to the assoc you mention


Is there no way to keep it pure?


And you invoke the effect by returning {::create-strip-token params} from the original handler


I mean, do I have to call (dispatch ...) this way?


The effect will not be pure of course


This is an effect, not an event handler


ie. reg-fx vs reg-event-fx


Event handlers you can keep pure. Effects are the place where you make your side effects.


or is it better to do them sequentially?


But what if all p1, p2, p3, p4 are scoped in the current handler, then do I need to first call:

{:dispatch [:event-foo p1 p2 p3 p4]}
and then in :event-foo call:
{:dispatch [:event-bar p3 p4}


I'm attempting to keep the functions pure


what does this error mean?:

Uncaught TypeError: lastCallbackNode is not a function
    at flushFirstCallback (scheduler.development.js:108)
    at flushImmediateWork (scheduler.development.js:170)
    at exports.unstable_runWithPriority (scheduler.development.js:262)
    at runWithPriority$2 (react-dom.development.js:11306)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11350)
    at flushSyncCallbackQueue (react-dom.development.js:11339)
    at scheduleWork (react-dom.development.js:21432)
    at Object.enqueueForceUpdate (react-dom.development.js:13146)
    at cmp.Component.forceUpdate (react.development.js:354)
    at Object.reagent$impl$batching$run_queue [as run_queue] (batching.cljs:38)