Fork me on GitHub
#reagent
<
2016-01-12
>
escherize00:01:43

As far as https://github.com/magomimmo/modern-cljs/tree/master/doc/second-edition, I found the first 4 chapters to be awesome re: explaining the boot build process.

escherize00:01:04

I did kind of veer away when it started getting into domina, etc.

mikethompson03:01:08

@jaen: > You could take a look at re-frame; it's not exactly redux, but inspired by it. For the record, this statement isn't true. re-frame was inspired by many things, but redux absolutely wasn't one of them. Redux didn't exist when re-frame was authored. Redux came much later. To give you a sense of timing, re-frame was published at roughly the same time that the "Elm Architecture" was published. To my knowledge they evolved around the same time. In designing re-frame I took some inspiration from the early Elm examples available in mid 2014. The Elm Architecture was not formally defined at that point, and I struggled to read the language -- no background in Haskell for me -- but I cottoned on to various concepts like Signals, foldp, lift etc. Most of the early Elm examples I can remember seemed to focus on how Signals were first class. Mouse position as a Signal etc. Games mostly as I remember it. So Elm influenced me to become very interested in FRP, and to understand what Reagent was doing through the lens of FRP, but I don't remember much about "Architecture" making its way into my head (that I'm aware of now). So, for me, the other, perhaps larger inspirations were Reagent itself, React/Flux, Hoplon, Pedestal, OM, etc. As I remember it, the approach of dispatch seemed to seep through from Pedestal, subscribe from Flux/Reagent.

mikethompson03:01:45

But its all a bit of a blur. My brain was very full of what were new concepts to me. But I can be quite sure of that redux didn't exist or act as any "inspiration" whatsoever.

meow04:01:17

have you seen the fun we've been having?

mikethompson04:01:07

Ah. Fending off the Slackpocalypse

mikethompson04:01:38

What database ?

meow04:01:49

not decided yet

mikethompson04:01:53

I'd point you in the direction of rethinkdb

mikethompson04:01:00

For anything realtime

mikethompson04:01:12

They have something called "fusion" currently in the works

meow04:01:16

that hackpad is open for edit

meow04:01:43

I know, I know, you're not much of a writer...

mikethompson04:01:45

I'm not actually. Its true!!

meow04:01:06

coulda fooled me and a whole lotta other folks

meow04:01:25

been paying a 👻 ✍️

mikethompson04:01:39

Writing is torture. Takes so long !!

meow04:01:13

👻 ✍️ ㊙️

mikethompson04:01:25

I can bearly write a slack comment without having to reedit it simple_smile

meow04:01:27

not a wrench

meow04:01:31

the new app is gonna have great edit features

meow04:01:53

also helping with #C0J20813K

meow04:01:20

one contender in the race to save us from :slackpocalypse:

mikethompson04:01:23

Will have a look.

meow04:01:56

so, I remember way back when you being interested in rethinkdb - been using it much?

mikethompson04:01:36

A bit. Not to its full potential yet.

meow04:01:17

will check it out, thanks

dvcrn07:01:09

I ran into a little problem with react native. Someone an idea? Following:

dvcrn07:01:41

Some components in react-native (mapview for example) require you to pass sub-components as properties:

title: 'More Info...',
        rightCalloutView: (
          <TouchableOpacity
            onPress={() => {
              alert('You Are Here');
            }}>
            <Image
              style={{width:30, height:30}}
              source={require('image!uie_thumb_selected')}
            />
          </TouchableOpacity>
How react-native works under the hood (afaik) is that it decodes data to JSON, passes it through the native bridge to objc which will then work with it and set things as native properties

meow07:01:32

@danielcompton: perhaps you know what to do about ^

dvcrn07:01:58

The problem I ran into is, that

(def view (r/adapt-react-class (.-View js/React)))
(def text (r/adapt-react-class (.-Text js/React)))

(.stringify js/JSON (r/as-element [view {:style {:flex 1}}
                                           [text {:style {:flex 1}} "test"]]))
Turns into a circular structure so when trying to stringify it, it throws TypeError: Converting circular structure to JSON

dvcrn07:01:15

I'm not sure if r/as-element is the right tool for this but in console the rendered component looks good to me

meow07:01:45

where is the circular structure

dvcrn07:01:57

somewhere in the rendered thing from as-element

meow08:01:36

how can you view it without passing it to stringify

dvcrn08:01:58

I dumped it into (.log js/console) or what do you mean?

jaen08:01:24

@mikethompson: I've just checked what was the original facebook's architectural proposal for React and it seems I've mixed up Flux with Redux for some reason '

jaen08:01:38

Sorry for mixing that up.

meow08:01:05

@jaen: can you help with ^

dvcrn08:01:18

@meow: thanks for the support simple_smile

jaen08:01:39

With RN? No idea, sorry. I don't even have smartphone : V

meow08:01:06

no, just with how to go about debugging

meow08:01:31

@jaen: you know more about this than I do

jaen08:01:21

Ah, I see. Well https://github.com/binaryage/cljs-devtools might help to understand a Clojurescript more clearly. But that's Javascript, right?

dvcrn08:01:19

yeah it's mostly javascript I believe

dvcrn08:01:44

I need to somehow get the exact same result from reagent that

<TouchableOpacity
            onPress={() => {
              alert('You Are Here');
            }}>
            <Image
              style={{width:30, height:30}}
              source={require('image!uie_thumb_selected')}
            />
          </TouchableOpacity>
would create

dvcrn08:01:28

or maybe this is a case where I need to escape to raw interpolated js, hmm

dvcrn08:01:51

let me try if a reagent-less version works

meow08:01:28

minimal is best

jaen08:01:05

And the obvious

(def touchable-opacity (reagent/adapt-react-class (.-TouchableOpacity js/React)))
(def image (reagent/adapt-react-class (.-Image js/React)))

(defn alert[content]
  (.alert (.-AlertIOS js/React) "" content))

[touchable-opacity {:on-press #(alert "You Are Here")}
  [image {:style {:wifth 30, :height 30} :source(not sure what here)}]]
doesn't work?

dvcrn08:01:18

the problem comes when passing a component as a property like [foo {:something [view (...)]}]

jaen08:01:34

And foo is something from RN?

meow08:01:39

foo is a play on FUBAR, which means fucked up beyond all repair

jaen08:01:45

If so, I'll try [foo {:something (reagent/as-element [view ...])}]

meow08:01:46

but we can't say fuck on slack

jaen08:01:16

I'm asking about semantic meaning not etymology P ;

meow08:01:24

i'm so bad

jaen08:01:48

Yeah, I can see you like to troll a bit ; d

meow08:01:11

reactji performance artists have that tendency

dvcrn08:01:03

@jaen are you actually trying with react-native right now?

jaen08:01:33

I can't, no smarpthone like I said ; d

jaen08:01:16

I suppose I could have tried with an Android emulator on muh loonix, but I don't have that set up.

jaen08:01:54

But in web-reagent land if you interact with something that came from js-React you usually have to call (reagent/as-element ...) on the hiccup vector of your component.

jaen08:01:01

So maybe the same would apply in RN-land.

dvcrn08:01:19

does it wrap the component with some reagent specific stuff or is it the pure react component like react would render it?

jaen08:01:44

(reagent/as-element ...) produces a plain React component from a reagent description of component.

jaen08:01:22

Form-3's are already plain React components IIRC, but form-1 and form-2 aren't and thus the need for as-element.

jaen08:01:02

Basically, React requires something derived from their Component class; for < ES6 React.createClass takes care of it. reagent/create-class uses it modulo some Clojurescript -> Javascript transforms.

jaen08:01:14

But form-1 and form-2 are - respectively - functions that return Clojurescript vectors and functions that return functions that return Clojurescript vectors. Both are not valid React components so you need to pass them through reagent/as-element so it appropriately calls reagent/create-class for you.

dvcrn08:01:28

I tried a direct call from cljs to js and don't have the error anymore:

(let [e1 (.createElement js/React (.-Image js/React) (clj->js
                                                              {:style {:width 30 :height 30}
                                                               :source {:uri ""}}))

              e2 (.createElement js/React (.-TouchableOpacity js/React) #js {} e1)]

(...)
Though still not working the way it should. I'm gonna experiment a little bit more

dvcrn08:01:49

but was my reagent call above wrong by chance? Because it if creates the same output, it shouldn't throw an error when passing into mapview

jaen08:01:11

Well, that looks kinda awful xD

jaen08:01:26

> was my reagent call above wrong by chance? Which one? I'm not sure which you refer to.

dvcrn08:01:37

just a sec, finishing this experiment up real fast

dvcrn08:01:52

ok the direct call to react works. Now to try the reagent approach again

jaen08:01:19

Sure. I think just using reagent/as-element should work, but let's see.

dvcrn09:01:00

phew! got it working with:

(set! js/React (js/require "react-native/Libraries/react-native/react-native.js"))
(def touchable-opacity (r/adapt-react-class (.-TouchableOpacity js/React)))
(def image (r/adapt-react-class (.-Image js/React)))

              (let [r1 (r/as-element [touchable-opacity {}
                                  [image {:style {:width 30 :height 30}
                                          :source {:uri "..."}}]])]

dvcrn09:01:16

I am not sure where the exact problem was but I am a happy hippo now simple_smile

dvcrn09:01:27

thanks a lot for the great assistance @jaen!

jaen09:01:14

@dvcrn: yup, that looks like it should have worked. I guess your problem was you were trying to pass [some-component {} ...], right?

jaen09:01:32

So you basically wanted to pass a whole Clojurescript persistent vector structure.

jaen09:01:45

No wonder it might have not wanted to serialise properly.

dvcrn09:01:09

No I had it already inside as-element

dvcrn09:01:16

It was something else

jaen09:01:16

Oh, then that's weird.

jaen09:01:52

But I can't find your original code so not sure what that could've been.

jaen09:01:57

Good you got it working though.

nbdam09:01:31

What is the best way to get something like react context/dynamic scoping in reagent? I want to avoid repetition and pass arguments to some descendants (not all of them and not necessarilly direct)...

jaen09:01:07

You can just use ratoms you have defined elsewhere as-is.

jaen09:01:37

(def counter (reagent/atom 0))

(defn component []
  [:div "Counter: " @counter])

nbdam09:01:47

Well, I would have to pass the reference to them in that case...

jaen09:01:28

As you can see - you don't. Reagent tracks dereferences to ratoms at runtime using a kind of dynamic scoping.

jaen09:01:30

So the above just works.

nbdam09:01:40

I didn't mean i would need to thread that value through all the functions, but I need it altogether... and I need many of this counters from your example so hardcoding it is not good...

jaen09:01:14

Oh, then I must have misunderstood what you want to achieve, sorry.

nbdam09:01:27

My example is maybe not the best...

nbdam09:01:55

This is I think analogue to what I wanted: If I model all my data in a single atom, and I want to avoid cursors (re-frame).. I have a bunch of inputs that all take edited property as a parameter. If all the props are paths withe the same prefix can the prefix be passed dynamically from the parent? I can use local functions to generate paths and avoid repetition, but just wandering....

jaen09:01:39

Hmmm... First off - re-frame is not cursors. For reading you have reactions which are function evaluations cached in an atom. For writing you have event handlers. So not really cursors.

jaen09:01:04

But about the real question - I'm not exactly sure how that could be approached. You mentioned Javascript-React doing it. Any example?

nbdam09:01:22

Haha, thats what I thought I said... about cursors.. I think I will avoid this for know by 'preprocessing' arguments to my components with a function that will fill needed data in without so much repetition... I just need to structure the components accordingly... I just wandered if there is an easy solution to this..

dvcrn09:01:23

you could of course pass the prefix as a component property down. {:data-from-parent {:prefix "foo"}} or something like that

meow09:01:37

does anyone use specter with reagent

nbdam09:01:45

I am passing it currently, but it is geting repetitive...

dvcrn09:01:01

I watched spectre but didn't use it yet 😛

nbdam09:01:04

I have been using specter a bit..

meow09:01:15

does it help with this

meow09:01:22

deep maps

nbdam09:01:22

I had quite a complicated model, and it certainly helped isolate the update functions into more composable parts...

dvcrn09:01:38

@nbdam: then how about a function / macro that wraps reagent and creates the component for you and automatically passes the parents reference down

nbdam09:01:02

Just that there are some other lense libs for cljs, and there is synthread so I don't know which are better...

nbdam09:01:10

I liked it all in all..

meow09:01:14

is this not addressed in any of the docs - oops, I was thinking about re-frame

meow09:01:26

what does mike recommend with re-frame

nbdam09:01:26

Mike posted synthread link recently, so he is probably looking into it... superficially it looks like it can be used to achieve many of the same things like specter..

meow09:01:48

I saw a new lens lib today

meow09:01:03

posted a link to it in braid

nbdam09:01:16

@dvcrn this is what I will probably do, make a builder function that will modify params to my components accordingly..

meow09:01:18

gotta think of something I can search on so I can go find it

meow09:01:30

braid is not like slack

meow09:01:02

were still working on the search capability

meow09:01:29

actually the search works great, I just can't think what to...

meow09:01:33

nevermind

meow09:01:06

no idea if it would help

meow09:01:16

just looked interesting

meow09:01:36

are any of the ideas from om.next making their way into reagent or do they remain separate beasts

dvcrn09:01:45

I think they should stay separate. I went to reagent because om became too much of a general framework like falcor or graphql

dvcrn09:01:22

the ideas are good but IMO it is too complex for most apps

dvcrn09:01:49

all I want is a wrapper around react and if I want more functionality then I take something like re-frame into the mix

jaen09:01:24

Om.prev is too complex as a React wrapper compared to reagent.

jaen09:01:34

And Om.next just solves different issues.

jaen09:01:46

Reagent is only a view layer, while Om.next is also a data layer.

jaen09:01:22

The approach Om.next has is something I agree is a great way to build more complex apps, but sometimes you just don't need that.

dvcrn09:01:25

I kinda liked om.prev 😛

jaen09:01:03

So yeah, I agree Om.next should not supersede reagent. But something like Om.next using reagent... that would be nice. In fact it's so nice I'm trying to make a thesis out of it : V

jaen09:01:13

Hah, Om.prev felt too verbose to me.

dvcrn09:01:14

well the query and mutation system next uses is very similar to reagent+re-frame

meow09:01:56

well, we were talking about the challenge of state management and lenses/cursors

meow09:01:20

so was wondering if any of that could fall out of om.next, but probably not

jaen09:01:24

Well, not exactly - re-frame takes care of the event loop, but does not impose on you how you updated your data. Om.next has this whole machinery for merging state.

meow09:01:50

right - but I see users struggle with data

jaen09:01:06

I think it could; composable component-scope queries and automatic data merging and normalisation it offers are great things.

jaen09:01:18

Just possibly a bit too much hassle for small scope.

dvcrn09:01:40

the thing that gave me probably the most headache was querying and remote querying

dvcrn09:01:34

questions like: how do I query the state with my query and queries from sub components and their sub-components. And then: Implement something on the server that does the same with an existing database if you don't use datomic

dvcrn09:01:44

my brain went 💥

dvcrn09:01:29

I actually have a fairly "popular" project written in om.next, just without the server stuff - https://github.com/dvcrn/markright. The server stuff killed me

jaen10:01:12

Well, I can't talk about how to exactly do that in practice since I didn't play with the implementation, just have been reading up on concepts like that since even before om.next was a thing (like Relay/GraphQL), but what it basically does it take your query and walk it like the tree it is, calling functions you registered for given types of vertices.

jaen10:01:44

And yeah, I can agree that figuring out how to write a server-side parser to construct SQL queries from that would be non-trivial.

dvcrn10:01:47

it is not simple_smile

jaen10:01:57

On the other hand - if you have an event sourced application or microservices it would be quite easy - you walk the query, make queries asynchronously and build up the response (if I understand correctly that's basically the idea behind how Falcor or GraphQL servers work).

jaen10:01:00

But with SQL? Yeah.

jaen10:01:23

It got me stumped enough that I decided to switch to event sourcing in my thesis to make it easier on me xD

dvcrn10:01:51

When I have enough free time I will definitely go into om.next territory again but for now I am very very happy that something like reagent+re-frame exists simple_smile

jaen10:01:32

Yeah, I can see that. For a simple CRUD-y application, where a backend maps to SQL queries it just might be not what you want.

jaen10:01:27

And working with reagent+re-frame will just be simpler and more fun.

dvcrn10:01:03

I am secretly hoping that someone writes a query fragment parser for django to support om until I start the next app 😛

jaen10:01:07

Django, ewww D :

jaen10:01:16

(I came from Ruby, Django always looked awful to me)

jaen10:01:41

Well, not sure about Om.next, but GraphQL parsers and servers will probably happen. Not sure why Om.next didn't decide to reuse that, but maybe the queries could be translatable between either?

meow10:01:05

I wonder who wrote the initial django pub/sub system

jaen10:01:16

Python is pretty cool as a language, but all the big things made in it, like Django, always looked awful to me for some reason.

meow10:01:33

cuz their big and awful

meow10:01:41

I never used django

meow10:01:03

they forked my event/pub/sub library for all their internal event handling

meow10:01:16

and then evolved it

jaen10:01:30

Oh, curious.

dvcrn10:01:41

Django is awesome. Never liked a framework this much before

dvcrn10:01:51

But I guess it comes down to personal preference

dvcrn10:01:43

What do you not like about it?

cjmurphy11:01:23

Jaen if you are writing a thesis that is somehow about a future great Client / Server framework, or thinking in that space, then just want to make sure you have heard of this one:

jaen11:01:08

I think I've came across it before; right now I'm just focusing on the synchronisation part, since that's the focus of the thesis, but if I ever decide to make a bigger framework out of that I'll be sure to keep it in mind. Thanks for reminding me of it.

meow13:01:04

@rafd: evaluate bureaucracy mentioned by @cjmurphy ^

rohit14:01:56

Does anyone have any suggestions for building a search input bar type component with reagent, where an external resource is fetched on change of the value of the input text? The complexity is that you don't have to fetch the resource on every keystroke but only if the text is stable ie it hasn't changed for x milliseconds. I've seen this being done using react-timer-mixin but wanted to ask if anyone has any experience?

rohit14:01:49

The issue I had with react-timer-mixin is that I just couldn't get it in a shape to be used in the browser. Its meant to be used with babel or something and I am not familiar with it

jaen14:01:03

If you need something that needs preprocessing with Clojurescript there's no running from webpack or browserify unfortunately.

jaen14:01:20

So you could process it with that and then use in :foreign-libs

jaen14:01:30

Or alternatively maybe write a debounce based on core.async?

meow14:01:37

I have no idea how they are doing it but the search input bar in #C0J20813K works as you described - at least, it works really well

meow15:01:18

@rafd: how do you guys do the search in braid?

rohit15:01:39

looks like #C0J20813K uses the same debounce function @jaen mentioned

jaen15:01:40

Slightly different it seems (probably the original; the one I linked says it was modified to make the first call after the timeout instead of at the beginning), but yeah.

jaen15:01:45

No problem

meow15:01:53

if you come up with something better let us know

michael.heuberger20:01:15

Hello folks, I've got a, probably noob, question regarding props in Reagent/React. How can something like this be achieved?

propTypes:
  age:  React.PropTypes.number.isRequired
  data: React.PropTypes.array
... I am fully aware that Clojure is very different and probably doesn't need that kind of hinting. But I think they are useful for stability/development.

jaen21:01:34

For such type validation Clojure land usually uses - https://github.com/Prismatic/schema

jaen21:01:03

Since props in reagent are just function arguments you can use schema's function annotations and validations.