Fork me on GitHub
#reagent
<
2018-04-11
>
pesterhazy07:04:33

that'd be cool!

pesterhazy07:04:45

@mattly I once started (but never completed) a tool like that: https://github.com/pesterhazy/unspector

pesterhazy07:04:57

another data inspector widget for clojure would be very welcome (there already is https://github.com/Odinodin/data-frisk-reagent which I love)

mattly16:04:41

yeah I looked at data-frisk, it’s not customizable enough for my needs

ajs08:04:44

A while back I was reading an article somewhere about a way to avoid form 2 components that merely need to be wrapped in local state atom by using some function or macro "with-state" or similar and then defining what looks like a form 1 component, but for the life of me I cannot find this information any more. Anyone have any idea what I'm talking about?

pesterhazy09:04:26

with-let is useful mainly for disposing of resources I think

ajs10:04:31

I don't follow -- what resources do you mean? Aren't they really quite the same, just syntactic sugar?

pesterhazy09:04:42

if you don't need that, Form-2 seems clearer to me

curlyfry09:04:31

Anyone here able to use [cljsjs/react-transition-group "2.2.1-1"] successfully? I seem to always get Undefined nameToPath for react_dom or Undefined nameToPath for react after including the dependency. I have tried with :exclusions [cljsjs/react], :exclusions [cljsjs/react-dom], and :exclusions [cljsjs/react cljsjs/react-dom]

curlyfry09:04:19

I'm using reagent 0.7.0

ajs10:04:31

I don't follow -- what resources do you mean? Aren't they really quite the same, just syntactic sugar?

pesterhazy15:04:04

with-let allows an optional finally clause, which gives you a chance to clean up after yourself

ajs17:04:40

Kind of like a "did-unmount" convenience

pesterhazy15:04:23

unless you need that feature, Form-2 seems clearer to me

justinlee16:04:57

@curlyfry you’ve got conflicting dependencies somewhere

curlyfry16:04:19

@lee.justin.m That was my suspicion, which is why I tried the different :exclusions i mentioned. Didn't help at all though.

justinlee16:04:04

are you using lein & cljsjs or some other mechanism to import?

justinlee16:04:32

I suspect that the version of r-t-g needs a version of react different from the one you are ending up with

juhoteperi16:04:44

No use just blindly adding exclusions, check dependencies tree to confirm conflicting versions and then use exclusions or other solutions to ensure correct versions

juhoteperi16:04:05

Oh I think I can guess the problem

juhoteperi16:04:42

React-transition-group Cljsjs package uses new-style names (to support global exports) so it tries to use react foreign-lib which is provided by new Cljsjs React packages, but not the old Cljsjs React version used by Reagent 0.7

juhoteperi16:04:25

[cljsjs/react "15.6.1-2"] [cljsjs/react-dom "15.6.1-2"] in addition to new react-transition-group package should work with Reagent 0.7

curlyfry17:04:54

@juhoteperi Hmm, interesting! Will try it tomorrow. Thank you!

curlyfry17:04:05

That seems a bit subtle though, not sure how one would be able to figure it out without keeping close attention to changes in cljs. It's also possible I'm just dense.

juhoteperi17:04:08

I'll try getting 0.8 out soon. Should help with this kinds of problems.

curlyfry17:04:41

Very much looking forward to 0.8 🙂

justinlee17:04:40

@curlyfry I don’t think it is reasonable. cljsjs is a fragile solution, in my opinion, and really only works when libraries are independent. as you try to add more react libraries into your program, for your sanity you’ve got to use another solution

curlyfry17:04:06

@lee.justin.m What aspects of cljsjs make it more fragile than other dependencies?

juhoteperi17:04:43

Some of these changes, like global-exports and using npm names on cljsjs libs, are to help with transition to other solutions, without breaking existing projects

justinlee17:04:56

for starters, if you have a single dependency that isn’t on cljsjs, suddenly the whole dependency management is broken

curlyfry17:04:04

interesting stuff, what solution are you using for js deps @lee.justin.m?

justinlee17:04:47

I go with shadow-cljs, but the webpack solution is robust too. https://gist.github.com/jmlsf/f41b46c43a31224f46a41b361356f04d

curlyfry17:04:49

I'll check it out. What about :npm-deps?

juhoteperi17:04:22

ClojureScript compiler Node module support (i.e. :npm-deps) is experimental feature

justinlee17:04:43

:npm-deps will run your library through advanced compilation and its resolution algorithm is not a 100% replica of npm, so it might work sometimes and get you good results, but it isn’t robust at all

justinlee17:04:12

also the error messages are just awful and unless you want to look at the source you’ll never be able to debug problems with it

juhoteperi17:04:54

0.8.0-rc1 is out now: https://github.com/reagent-project/reagent/blob/master/CHANGELOG.md#080-rc1-2018-04-11 Not planning any more changes but I decided for one more release before final to ensure defaulting to React 16 doesn't cause huge problems.

athomasoriginal17:04:44

Question about r/current-component I have heard some argue that they do not use this as it adds too much OO into clojure. In preference, they might do something like:

(def node (atom nil))

:component-did-mount
(fn [this]
  (reset! node this))
Essentially these are doing a similar thing. I just want to understand what others think about this? > To clarify, the atom in declared in the clojure function containing this reagent class

justinlee18:04:16

@tkjone Why do you need the current component outside of the lifecycle methods anyway? The question to me is confusing.

athomasoriginal18:04:50

Let me add some more code:

(defn some-component
  [_]
  (let [node (atom nil)
       other-func (;;using r/props here)]

      (r/create-class 
          :component-did-mount
             ;; stuff here))

athomasoriginal18:04:36

where I have written ;;using r/props here we are using this we stored in the node atom above. So its a way to access this.props in a claasic react way

justinlee18:04:52

where does other-func get called? if its being called from the render-func you can just close over the props there. if its being called from the lifecycle funcs, you can get props from this and then pass them in

justinlee18:04:25

but to answer your question: the “OO” aspects are inherently introduced by react, not reagent. I don’t see how either method makes it more or less “OO”

athomasoriginal18:04:03

other-func is called in :reagent-render

justinlee18:04:21

So you have the props right there, don’t you?

justinlee18:04:40

the reagent-render’s argv is the props

athomasoriginal18:04:05

sorry, other-func is passed to another component in :reagent-render

athomasoriginal18:04:14

so its not called till later

justinlee18:04:52

whoa that is confusing 🙂

justinlee18:04:58

whose props does it want?

athomasoriginal18:04:12

the parent component

justinlee18:04:49

if you want a non-OO solution, maybe the better thing to do is use partial with other-func before you pass it

athomasoriginal18:04:33

are there examples of this in the wild?

justinlee18:04:46

i haven’t needed it. but it would be somethinge like (defn f [prop1 prop2 something-else] ...) then when you pass it, instead of passing f, you pass (partial f prop1 prop2)

justinlee18:04:13

then when it is called you pass something-else assuming it needs more args

athomasoriginal18:04:17

in the end, I wanted to vet this approach, I don't see a need either.

justinlee18:04:11

I’m converting javascript to cljs right now. I use partial sometimes when I want to break a class method out of the class and make it a function, but you need a particular signature b/c its a callback. In JS, you just set stuff on this and then make the signature whatever it needs. In cljs, you can add the data that was previously set on this to the function signature, then use partial to bind them.

athomasoriginal18:04:11

Interesting. So you are using partial, as an example, if you have a class and said class has functions defined inside of it. This allows you to remove those functions in the class so they are standalone functions

athomasoriginal18:04:53

how do you deal with the case where this extracted function now requires so many args because previous, it could just access variables as they were in its scope?

justinlee18:04:23

I don’t know what the right solution is. I only use this technique when the function “feels” like it can or should be standalone (which is more often than you’d think). If there’s inherently a lot of data being passed, then maybe the solution is to pass a big map that effectively operates as “this”. One of my components renders a pdf to a canvas and is just inherently a big ugly stateful class. I literally merge the props into a state atom and just mutate it like it was the this

justinlee18:04:53

btw long potentially relevant thread on this in #clojure

justinlee18:04:09

But my basic rule is that if you can get away with just passing two or three things, do it. The function is easier to understand not only in terms of understanding its implementation, but also in terms of understanding its use at the callsite.

athomasoriginal18:04:10

That has been my approach also.

athomasoriginal18:04:21

the conversation you are referring to is the thread, yes?

justinlee18:04:41

yea. kind of related in an abstract way

athomasoriginal18:04:43

I would like to see how dnolen would handle these situations in real world apps.

justinlee18:04:05

the real world is an ugly place with no room for purity 🙂

gklijs19:04:33

That reminded me of a quote from Divid Nolen, "The world is messy, and it's only though experience that you realise how do we manage the messiness of the real world." Witch for me really was an eye opener with respect to static typing and how this is already kind of a misrepresentation if the 'real' world.

athomasoriginal18:04:33

Very true, and I feel that Clojure and the maintainers understand this. Just need some examples 😉

athomasoriginal18:04:48

This is where pragmatism takes over

justinlee18:04:14

I basically have fallbacks (like the big state object that takes the place of this and big let bindings that are basically imperative code) so that I can just get stuff done. As time goes on and I get better at cljs, I take the opportunity to make things cleaner.