re-frame

https://github.com/Day8/re-frame/blob/master/docs/README.md https://github.com/Day8/re-frame/blob/master/docs/External-Resources.md
Spaceman 2020-06-18T03:49:37.416200Z

I have a subscription :show-payme that is set to true. When it is set to true, a div is mounted:

(if @(subscribe [:show-payme]
   [:div {:id "card-element"}]
)
I have an fx event that returns the following:
{:db {:show-payme true}
  :dispatch [:load-stripe]}
the load-stripe fx event contains the following:
(.mount card-element "#card-element")
The problem is that the .mount is being called before the #card-element div ever mounts on the page, which is causing the #card-element Element Not Found error. How do I get around this?

Spaceman 2020-06-18T03:51:05.417Z

I want the #card-element to be mounted before the load-stripe dispatch is called

p-himik 2020-06-18T04:32:25.417200Z

That's what React lifecycle methods are for. Unless the JS library requires DOM elements' IDs, you should never use them. Instead, set a React ref in :reagent-render and run the JS code that uses that ref in :component-did-mount.

Spaceman 2020-06-18T04:33:39.417400Z

I've never used :reagent-render. Can you please show a minimal example what you mean?

Spaceman 2020-06-18T04:41:10.417900Z

I don't see how to mount the stripe element into that empty div without using the id. I instead removed the load-stripe dispatch, and changed to the following:

(def load-stripe (with-meta identity {:component-did-mount (dispatch [:load-stripe])}))
[load-stripe [:div {:id "card-element"}]]
But I get: Uncaught (in promise) IntegrationError: We could not retrieve data from the specified Element. Please make sure the Element you are attempting to use is still mounted. at new t (https://js.stripe.com/v3/:1:10981) at _o (https://js.stripe.com/v3/:1:53784) at e._handleMessage (https://js.stripe.com/v3/:1:60201) at e._handleMessage (https://js.stripe.com/v3/:1:27512) at https://js.stripe.com/v3/:1:58803

Spaceman 2020-06-18T04:42:27.418100Z

that load-stripe wrap is supposed to trigger the :load-stripe dispatch when the container div is mounted

Spaceman 2020-06-18T04:45:22.418500Z

it works like the technique in the GitHub link but I find it more elegant

p-himik 2020-06-18T04:48:49.418800Z

> I don't see how to mount the stripe element into that empty div without using the id. Read about React refs and look around for examples.

p-himik 2020-06-18T04:49:12.419Z

{:component-did-mount (dispatch [:load-stripe])} is completely wrong. It has to be a function, not a result of the call to dispatch.

Spaceman 2020-06-18T04:49:47.419200Z

I meant #(dispatch ...)

p-himik 2020-06-18T04:49:51.419400Z

And don't load Stripe in an effect handler, since it requires an element. Just load Stripe in :component-did-mount. You don't need IDs for that.

p-himik 2020-06-18T04:50:16.419600Z

You never need IDs with React for something that's able to receive instances of DOM elements.

Spaceman 2020-06-18T04:50:58.419800Z

how do I do that? (.mount card-element "#card-element") becomes what?

p-himik 2020-06-18T04:52:05.420Z

(.mount card-element the-element), I imagine.

Spaceman 2020-06-18T05:00:37.420200Z

so I did {:component-did-mount #(dispatch [:load-stripe %])} and replaced the id with that new parameter

Spaceman 2020-06-18T05:01:40.420500Z

but that gives me:

Uncaught IntegrationError: Invalid DOM element. Make sure to call mount() with a valid DOM element or selector.
    at new t (<https://js.stripe.com/v3/:1:10981>)
    at t.&lt;anonymous&gt; (<https://js.stripe.com/v3/:1:107809>)
    at t.mount (<https://js.stripe.com/v3/:1:27512>)
    at eval (<http://localhost:3000/js/cljs-runtime/vendo.events.js:107:14>)
    at eval (<http://localhost:3000/js/cljs-runtime/re_frame.std_interceptors.js:157:236>)
    at re_frame$std_interceptors$fx_handler__GT_interceptor_$_fx_handler_before (<http://localhost:3000/js/cljs-runtime/re_frame.std_interceptors.js:167:4>)
    at Object.re_frame$interceptor$invoke_interceptor_fn [as invoke_interceptor_fn] (<http://localhost:3000/js/cljs-runtime/re_frame.interceptor.js:224:88>)
    at Object.re_frame$interceptor$invoke_interceptors [as invoke_interceptors] (<http://localhost:3000/js/cljs-runtime/re_frame.interceptor.js:263:37>)
    at Object.re_frame$interceptor$execute [as execute] (<http://localhost:3000/js/cljs-runtime/re_frame.interceptor.js:380:108>)
    at Object.re_frame$events$handle [as handle] (<http://localhost:3000/js/cljs-runtime/re_frame.events.js:93:22>)

p-himik 2020-06-18T05:04:32.420700Z

That's not the correct usage. If someone that tries to help you asks you to do something, please do that. In this case, please read about React refs and look for ref examples in Reagent. I have already given you absolutely all information that you need to make it work.

Spaceman 2020-06-18T05:08:15.420900Z

"Refs are created using React.createRef() and attached to React elements via the `ref`attribute" But we're not supposed to use the React object, right?

p-himik 2020-06-18T05:10:49.421200Z

Ehm, no? I don't know where you got that idea, but it's absolutely fine to use React objects.

Spaceman 2020-06-18T05:12:22.421500Z

okay this is the way to do it:

<https://github.com/reagent-project/reagent/issues/5>

Spaceman 2020-06-18T05:12:52.421700Z

I think

Spaceman 2020-06-18T05:15:24.421900Z

I like my way using the id, but I don't know why I'm getting the error though. The div is mounted and then the dispatch is being triggered.

Spaceman 2020-06-18T05:19:52.422100Z

that card-element id div is supposed to be in the dom before the (.mount card-element "#card-element") is called

Spaceman 2020-06-18T05:20:34.422300Z

yet I get the error to make sure that #card-element div is still mounted

Oz 2020-06-18T09:10:39.429400Z

Hi there, I have a small state management challenge: I'm making an app for a robot that feeds fishes, the robot travels between the pools, that are shown as a grid of elements while the robot is shown as an icon. Initially, I just let the robot appear and disappear in different pools when its position changes, so the robot-icon component was managed by each pool. But then I thought it could be fancier to show the robot moving between the pools. So I took the robot-icon component out of the pool, and let the pools-map component trigger a function to reposition it whenever needed, and this way the movement can be animated. There is one problem: When screen get resized, the robot position changes. So another function is needed to reposition it and this seems like trouble. Now, I may go back to the blinking robots solution, as the animation is not that important, but I think its an interesting problem. What do you think is the way to do it? Edit: How it is related to re-frame? The robot position(which pool it should be in) is obtained from an event subscription, And the app uses breaking-point so events are dispatched when the window size changes.

p-himik 2020-06-18T09:18:05.429800Z

Not sure how it's related to re-frame. Either way, you can store the robot's position as percentages. It will work, unless window size changes also cause layout changes.

1👍
grumplet 2020-06-18T09:29:58.433500Z

Is it possible to query the list of registered subscriptions or the list of registered events from the public re-frame API? I’m reading event and subscription keys in from overlapping datasets, and want to check whether they have already been registered. If not, what would happen

grumplet 2020-06-18T09:30:27.434100Z

if I made a duplicate registration… OK I can try and see..

p-himik 2020-06-18T09:31:48.434300Z

It would just override the previously registered one, with a warning in JS console.

p-himik 2020-06-18T09:33:40.434500Z

The public API to check would be (re-frame.registrar/get-handler :sub my-id) for subs. For events, replace :sub with :event.

1✔️
Oz 2020-06-18T09:33:51.434700Z

The robot position(which pool it should be in) is obtained from an event subscription, And the app uses breaking-point so events are dispatched when the window size changes. So I thought maybe it should be a combination of these subscription. Maybe using percentages is enough though :)

2020-06-18T09:34:16.434900Z

Yeah the latest version of re-frame will give you a warning on initial application load if handlers are overwritten (but not on hot reload)

2020-06-18T09:35:07.435200Z

(Older versions of re-frame gave overwrite warnings even on hot reloading, which is noisy and less helpful)

2020-06-18T09:36:42.435700Z

re-frame.registrar/get-handler is not public API (but it will work for exploratory purposes)

p-himik 2020-06-18T09:36:51.435900Z

Just to make sure it's clear - there will be no warning after the initial app load even if you register a handler under an existing ID deliberately and not as a part of hot reload.

p-himik 2020-06-18T09:38:17.436200Z

@mikethompson Oh. But how can one tell what's public API and what's not?

grumplet 2020-06-18T10:00:54.436700Z

Thanks @mikethompson @p-himik. This could happen in production code, which is why I want to make sure I’m handling the possibility correctly.

grumplet 2020-06-18T10:01:46.436900Z

I guess I can only access re-frame.registrar by adding it to the classpath.

grumplet 2020-06-18T10:02:16.437100Z

• in addition to re-frame.core I mean.

p-himik 2020-06-18T10:03:37.437300Z

re-frame's jar is on the classpath already. You just require re-frame.registrar in your namespace.

2020-06-18T10:30:21.437500Z

@p-himik re-frame.core is the public API

1👍
2020-06-18T10:31:02.437800Z

That's the part we try not to break

lepistane 2020-06-18T10:45:32.438200Z

managed to get it working with

(defn view [&amp; [props &amp; children]]
  (let [config (rf/subscribe [:app-config/all])]
    (reduce conj [:&gt; rn/View (merge {:style {:flex 1
                                             :flex-direction (:orientation @config)}}
                                    props)]
            children)))
the question i have now is why the other one was breaking

dazld 2020-06-18T11:26:00.438400Z

you could also cheat and use css 🙂

dazld 2020-06-18T11:26:07.438600Z

let the browser handle the transitions

1👍
dazld 2020-06-18T11:26:27.438800Z

no need to do that imperatively, if all you want is to animate the position change

dazld 2020-06-18T11:28:00.439Z

(not really cheating, but you get what i mean)

lepistane 2020-06-18T11:56:23.439200Z

SOLVED:

(defn view
  "reference <https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md#form-2--a-function-returning-a-function>"
  [&amp; [props &amp; children]]
  (let [config (rf/subscribe [:app-config/all])]
    (fn [&amp; [props &amp; children]]
      (let [{:keys [orientation]} @config]
        (reduce conj [:&gt; rn/View (merge {:style {:flex 1
                                                 :flex-direction orientation}}
                                        props)]
                children)))))

Oz 2020-06-18T13:32:34.439500Z

Well, If i want the element to change its position to another element's position, I need to set the top of my icon to the target's http://getBoundingClientRect.top I do this set in a react hook. But this position is given in pixels, and changes when the screen resizes. I think that the resizing problem is mostly because I didn't got the css right, because mixing relative and absolute positioning is confusing. Another option is using some sleight of hand - When the icon changes pool, move it there, then remove it, and add a new icon in the new pool. this should allow its position to be relative, and avoid the trouble of mixing absolute position.

2020-06-18T15:20:42.440100Z

Why would global interceptor be useful?

p-himik 2020-06-18T15:21:31.440200Z

Some discussion in the original issue: https://github.com/day8/re-frame/issues/570

2020-06-18T15:26:19.441400Z

So how would you track a value under :x with a global interceptor?

p-himik 2020-06-18T15:27:11.441900Z

With the on-changes standard interceptor, for example.

Harshana 2020-06-18T15:59:05.444700Z

Hey all. I'm new to re-frame and I have to write tests for my event handlers. I had a few doubts: How do I use the day8.reframe.test library in my file? (I tried using this but it says The required namespace is not available 😞 ) What are test fixtures?

jeff tang 2020-06-18T16:21:05.445800Z

I’ve tried re-posh but don’t really love it. Thoughts on putting a posh db inside of re-frame? Or generally speaking any atom inside app-db?

lilactown 2020-06-18T16:25:22.446100Z

why put it in the app-db?

jeff tang 2020-06-18T16:30:02.447900Z

so many components, function, etc. use posh . you’re right, it could be its own global as well. but I’m not sure that’s the best option

lilactown 2020-06-18T16:35:04.448400Z

yeah, I don’t really see the benefits of putting it in the app-db

lilactown 2020-06-18T16:35:38.449Z

if you’d like to use re-frame’s event/effect system, you can write an effect that writes to a posh db instead

jeff tang 2020-06-18T16:37:01.449300Z

cool, thanks @lilactown

2👍
jeff tang 2020-06-18T16:39:55.449700Z

Would you happen to have any input on https://clojurians.slack.com/archives/C07V8N22C/p1592497389093700

dazld 2020-06-18T17:09:11.450Z

you've got transforms too!

1👍
dazld 2020-06-18T17:09:34.450200Z

can set a position with transform and transition will perform the.. er.. transitions

1👍
2020-06-18T19:18:21.451900Z

Can you mix re-posh and re-frame? For example having a re-frame subscription depending on a re-posh subscription?

lilactown 2020-06-18T19:39:13.452600Z

AFAIK a re-posh sub is the same a re-frame sub so you should be able to compose them the same way you would any other re-frame sub

1❤️1🙂1🎉
Spaceman 2020-06-18T23:47:13.453800Z

how to find the line number of the re-frame code that throws the error:

[Error] Error: ["unrecognized request format: " nil]
	(anonymous function) (re_frame.router.js:6)
	(anonymous function) (re_frame.router.js:359)
	(anonymous function) (re_frame.router.js:425:110)
	(anonymous function) (re_frame.router.js:552)
	(anonymous function) (re_frame.router.js:291)
	(anonymous function) (re_frame.router.js:383)
	(anonymous function) (re_frame.router.js:425:110)
	G__67540 (re_frame.router.js:336)
	(anonymous function) (goog.async.nexttick.js:98)