Fork me on GitHub
#re-frame
<
2018-04-12
>
kenny00:04:04

Or perhaps name the function dispatch-<event-name>:

(defmacro def-event-fx
  [name docstring attr-map params body]
  `(do
     (defn ~name
       ~docstring
       ~params
       ~body)
     (defn dispatch-~name
       [event-vec#]
       (rf/dispatch event-vec#))
     (rf/reg-event-fx ~name ~name)))

(def-event-fx my-event
  {}
  [cofx event-vec]
  ;; handle my event
  )

;; dispatch the event
(dispatch-my-event [event args])

kenny00:04:03

It'd probably be better to be explicit about the dispatch rather than implicitly creating a dispatch function.

kenny01:04:23

Going to try out this impl in our CLJS app to see how things shake out:

#?(:clj
   (defmacro def-rf*
     [ctor name docstring attr-map params body]
     `(let [v# (defn ~name ~docstring ~params ~body)]
        (~ctor ~(symbol (str *ns*) (str name)) ~attr-map ~name)
        v#)))

#?(:clj
   (defmacro def-event-fx
     ([name attr-map params body] `(def-event-fx ~name "" ~attr-map ~params ~body))
     ([name docstring attr-map params body]
      `(def-rf* reg-event-fx ~name ~docstring ~attr-map ~params ~body))))

mikethompson03:04:04

@kenny ^^^ I plan to finish that document off a bit more and then open up a repo issue for discussion. Might be a week away.

4
deg13:04:25

One branch of my db tree is parameters that I want to allow my users to edit via a component. (all strings or ints) Does any library offer an easy way of doing this? For my current user-base, I don't need to make it pretty; just usable. So, I don't care exactly how it looks and I'm open to arranging the data and meta-data in whatever format works. I'd just rather use something ready to go, rather than wasting time coding something that will probably be thrown away soon.

richiardiandrea15:04:26

Have you folks deleted the rant against redux/relay? I need to read that every now and then (and hand it to JS .....colleagues 😃)

richiardiandrea15:04:37

Cannot find it anymore on GitHub

richiardiandrea15:04:43

Oh maybe it was all just a dream

akiroz17:04:03

Haven't seen it myself, but I could probably guess what it was about having been forced to use redux at work.... 😞 Only made it worse that I've used re-frame before that.

akiroz17:04:15

Almost snapped the first time I saw something like this in production:

// MyComponent/actions.js
const MY_COMPONENT_MY_ACTION = "MyComponent.myAction";

// MyComponent/actionCreators.js
function doMyAction(foo) {
  return {
    type: actions.MY_COMPONENT_MY_ACTION,
    foo
  };
}

// MyComponent/reducer.js
const reducers = {
  [actions.MY_COMPONENT_MY_ACTION]: (state, action) => {
    // do stuff here
  }
}

// MyComponent/index.js
<button onClick={this.props.doMyAction(123)}/>

function mapDispatchToProps(dispatch) {
  return {
    doMyAction: (foo) => dispatch(doMyAction(foo))
  };
}
... and the app was pretty big too.

brycecovert21:04:36

Are there recommendations for building reusable components that need to trigger effects? For example, if I’m going to create a company-table component that needs to query for companies when it’s mounted, and may need to re-query (say, if you go to the next page). Re-frame patterns seem straightforward when there’s only one, but if this gets componentized, perhaps used multiple times on a single page, it becomes less clear how the events and effects should work

brycecovert21:04:41

I could imagine: 1) the outer component that mounts the company-table will query for them, and pass the subscription as a parameter. The outer component passes event-handlers for changes as parameters, which dispatch events to trigger reloads 2) Have event handlers/subscriptions within the component, specifically for the table

hoopes21:04:14

Hi, I'm looking for examples of nested routing where functions representing the more "general" routes are hit before more specific routes. For example, if there were two routes for /admin/users and /admin/posts, the routing lib would detect that I'm attempting to enter the /admin route regardless of the sub-route, and check that my authenticated account has access. This may already be supported (currently trying to get familiar with bidi), but I haven't seen an example of it yet. Any help/pointers/links would be greatly appreciated. (Is stately my best bet for this?)

kenny21:04:59

@hoopes Can you add a function to the route-changed handler that executes your special admin logic when the path .startsWith "/admin"?

hoopes21:04:59

yeah, i think i could. i'm trying to transition from angular 1 (!), which actually had a pretty sweet router, which you could lay out with a big JS object - i was hoping to define my routes with a big cljs map (like bidi does), but have the route matching done for me throughout, with the nested routes working their way down from the "top", know what i mean? (maybe bidi already does this, and i just haven't come across it yet - i'm pretty new here in cljs land). if functions on the route change handler are the best way to do it, that's cool, i was just looking around for best practices

kenny21:04:04

I get what you're after. I don't use bidi so I'm not sure there. Though, this sounds like logic that you want to have in the backend, not the frontend.

hoopes21:04:27

maybe, but once i serve my giant main.js file, i'm pretty much only frontend, right? instead of the /admin check, imagine something not security related 🙂

kenny21:04:02

Even if you try to restrict parts of your app in the frontend, a user can still access it because all the code is in main.js.

kenny22:04:22

i.e. A user may be able to visit /admin/users in your app but no information will be shown to them because the backend will not load the required data.

hoopes22:04:52

oh sure - creds checking on the backend too, i was just using /admin as an example of a "high-level" point to do something that applies to the whole section you're looking at in the frontend app. I'm trying to run functions based on every URL match, instead of just the most specific one.

mikethompson22:04:34

@richiardiandrea never been anything ranting about redux in the official docs

richiardiandrea22:04:48

Uhm so maybe it really was a dream!

kenny22:04:29

Gotcha. All of the routes in our app have a parent page defined like this:

(derive :page/profile-password :page/profile)
You could probably do something similar for your admin page...
(derive :page/admin :page/admin-users)
(derive :page/admin :page/admin-posts)

kenny22:04:56

Then you can check if the page is an admin page via isa?.

hoopes22:04:00

yeah! something like that... i dunno, i'm gonna keep banging around with bidi - thanks so much for your help!

4
brycecovert22:04:37

@mikethompson thanks. I hadn’t seen that. Both of my approaches follow that pattern. That is, component-will-mount just dispatches an event

brycecovert22:04:27

The complexity to me is the globalness of the event when trying to make something reusable. “localized” events have to be explicitly so.

brycecovert22:04:13

i.e., you’d have to have an identifier as part of the event tuple for each instance

mikethompson22:04:17

@brycecovert yeah I understand the "locality" arguments but for me its a bad trade. Gotta go, sorry.

brycecovert22:04:37

bad trade? thanks for the pointers!