Fork me on GitHub
#re-frame
<
2021-01-11
>
Mikko Koski08:01:56

Does anyone remember what's the original source of this code? (defmacro def-sub [name & args] {:pre [(symbol? name)]} (let [kw (keyword (ns-name *ns*) (str name "|sub"))] (do` (def ~name ~kw) ~(macroexpand (rf/reg-sub ~kw ~@args)))))` Someone posted here on this channel list to Gist with this piece of code some time ago. I wrote down this piece of code and a link to the discussion (https://clojurians.slack.com/archives/C073DKH9P/p1591371104264100) where it was discussed but I can't access it anymore because it's too old.

Mikko Koski08:01:36

Oh haha, nvm, problem solved 😄 Even though I can't access the link the with my browser, the moment I posted it here Slack embedded the message here and I can now see the link to the Gist 😄

tugh09:01:34

Is there a lib for interacting with dom elements? Something like predefined coeffects and effects like :get-element-by-id :set-inner-html

p-himik09:01:54

I've never seen it. And I would be very cautious about mixing DOM manipulation and re-frame machinery. What's the underlying problem - why do you need to alter DOM manually when you're using React?

tugh11:01:24

I have a div with many children and want to set all of their width to the widest one. I've a :component-did-mount callback like below:

{:component-did-mount #(dispatch [::events/assoc-current-state
                                     :option-style
                                     {:width   (utils/max-child-width (str key "-options"))
                                      :opacity 1}])
:reagent-render ...)

tugh11:01:52

:option-style is passed through the corresponding functions

tugh11:01:27

which means i'm not creating side-effects by manipulation dom/dom properties. it is received from subscription

tugh11:01:20

the problem is utils/max-child-width is not pure:

(defn- children
  "Finds child nodes of a DOM element by id."
  [id]
  (some-> id
          dom/getElement
          .-childNodes
          array-seq))

(defn max-child-width
  "Finds width of the widest child. Returns nil when there are no children."
  [id]
  (->> (children id)
       (map #(.-offsetWidth %))
       (apply max)))

p-himik11:01:14

> I have a div with many children and want to set all of their width to the widest one. I am almost 100% sure that you can do that with CSS. Even if it's not possible for some reason - don't use re-frame for that. Use Reagent, especially since you're already using lifecycle methods.

tugh11:01:06

Well, I was also very believed in that I can solve this via CSS but no luck. All children contain an arbitrary text and I won't be able to know which child takes how much space before render.

tugh11:01:31

To clarify, I don't want all children to take all of the width of the parent

tugh11:01:39

so flex is not an option

tugh11:01:14

I want to find(or calculate beforehand, if possible) the widest child's width

tugh11:01:06

Can you eloborate on "don't use re-frame for that. Use Reagent,"

tugh11:01:34

Should I avoid using events&subs for this kind of thing?

p-himik11:01:59

> To clarify, I don't want all children to take all of the width of the parent Is introducing an intermediate div not an option? The you won't touch the parent div that you don't want to touch. Also, there are other solutions than flexbox. One that I know of is grid. Maybe there are others. Hard to come up with something without knowing your markup and requirements. > Should I avoid using events&subs for this kind of thing? Absolutely. Re-frame is for managing your app's state. A width of a particular div just to make it look nice is not your app's state, it's just some incidental representation.

tugh12:01:41

Introducing an intermediate dive is an option but I don't understand how it could solve my problem.

tugh12:01:16

I also keep some flags in my app state. one example is :show-more? which stores a boolean for a switch button

tugh12:01:58

is that also bad? I was using local states with reagent atoms but it feel cleaner to use the app db

tugh12:01:29

another reason is not losing the switch's state after hot reload

p-himik13:01:33

You said it yourself - it's switch's state. When something is a state that you care about, store it in app-db. IMO when the width of some element is not representative of anything in your domain model, it shouldn't be considered state. YMMV.

🙃 4
tugh14:01:54

Thanks for your help! 🙌

👍 4
lassemaatta09:01:23

I'm doing some maintenance work on an old re-frame app, where the original author has used the following pattern several times (in addition to more traditional reg-sub subscriptions). This was the authors first clojure(script) project. Am I right to assume that this could be replaced with a simpler reg-sub subscription or does the reg-sub-raw + reaction do something special here?

lassemaatta09:01:07

This is pretty much identical to the examples given for reg-sub-raw in the re-frame docs, but I'm slightly confused why go through all this when reg-sub does the same thing.

mikethompson09:01:51

reg-sub wasn't there for very early re-frame

lassemaatta09:01:17

that might explain it, based on the git history the initial version used was 0.4.1

mikethompson09:01:20

Maybe the author originally used register-sub (now deprecated) and then moved to reg-sub-raw and never made the jump to the new reg-sub

mikethompson09:01:37

But you are right ... that should now be written as something like:

(reg-sub 
  :something 
  (fn [db [_ & path]    ;;  <-- note the underscore
     (get-in db path)))

lassemaatta09:01:20

yeah, I found a commit where a bunch of register-sub s where changed to either reg-sub or reg-sub-raw (when calls to subscribe were needed)

lassemaatta09:01:52

perhaps it wasn't possible to provide the signal function back then, so reg-sub-raw was the only possibility

lassemaatta09:01:08

in any case, this solves my problem, thanks 🙂