Fork me on GitHub
#clojure-uk
<
2017-11-06
>
thomas08:11:01

moin moin morning

jasonbell08:11:46

For anyone looking for a change, Morgan McKinley are looking for 1 x backend Clojure dev and one front end in the 50k-70k region. https://www.morganmckinley.co.uk/job-details/887808 it’s for a financial startup called All Street Research, looks interesting if you like machine learning and text mining. I was asked but declined so thought I’d mention it here.

maleghast10:11:55

Morning All!

maleghast11:11:17

Morning @dominicm - How was your weekend?

maleghast11:11:03

@jasonbell - Thanks for the heads-up - I’m not currently looking, but it’s always encouraging to see that there are Clojure jobs “flying around” 😉

dominicm11:11:25

It was quite nice. I did some baking, and also made a useful thing: https://github.com/SevereOverfl0w/vim-replant How was yours @maleghast?

maleghast11:11:39

Lovely thanks @dominicm - had my parents here, so adventures with Granny and Grandpa… 😉 My kids have chickenpox, however, so now I am working from home, from the HOUSE OF POX and they are not very unwell with it so there have been several conversations about the noise level! 😉

maleghast11:11:57

Vim stuff looks good 🙂

dominicm11:11:32

Quite excited about the refresh. It makes switching projects pretty seamless, your binding of ,rf works no matter what. No worrying about what order to run things (and which namespaces they're all in)

dominicm11:11:07

Just processed the > they are not very unwell with it 😂 Poor you

maleghast11:11:17

(was on a call)

maleghast12:11:46

OK, so UK Clojure Peoples… I am using Reagent and I like it, so for now I don’t want to have to make big changes… If you had to start adding maps to your cljs/reagent interface(s), what library / libraries would y’all use? I am looking at react-leaflet as an obvious candidate, but would like to think I’d at least asked around to try to discover something better…

yogidevbear12:11:08

@maleghast I was reading up on Reagent yesterday and this morning and was about to ask how many people here were using it, but you beat me to the discussion with probably a better line of questioning 🙂 How are you finding Reagent so far?

maleghast12:11:06

@yogidevbear - I really like it. I was just on a conference call and my colleague asked “how easy would it be to move those radial bar graphs to down the left side?” and I had it done in less than a minute.

maleghast12:11:12

Really is very user-friendly and productive.

thomas12:11:15

I like Reagent... seems simpler compared to re-frame

maleghast12:11:35

I am SURE there will be a downside at some point, but for what I am doing right now it really seems excellent.

mccraigmccraig12:11:40

reagent is great. re-frame is also great too. if your project is bigger than small then you probably will want something to help you out with managing your state. whether that is a library or a set of conventions is up to you, but if you are newish to reagent and contemplating a significant project then i would suggest going with re-frame - it's sensible and they have taken care to help you avoid some of the possible pitfalls of reagent projects

maleghast12:11:31

@mccraigmccraig - I am interested by what you are saying here… What would you say qualifies as a “significant” project..?

Rachel Westmacott12:11:47

I also think that reagent is great. I have no opinion on re-frame.

maleghast12:11:48

(I don’t really have a lot of time on my hands and I’ve invested a lot of it already in reagent)

mccraigmccraig12:11:38

re-frame is reagent + state management stuff, so time you have invested in reagent is not wasted if you go re-frame

maleghast12:11:51

Oooh, ok - this sounds excellent imho

maleghast12:11:10

I will go look at the re-frame project page and see what’s what, in that case - thanks!

mccraigmccraig12:11:31

the re-frame docs are pretty good

maleghast12:11:39

P.S. Anyone got any particular mapping recommendations in the React / Reagent space that are “you need this it’s better than leaflet”?

mccraigmccraig12:11:21

the state management stuff consists of a few bits - here's a simplified description [1] single source of truth - the app-db, basically a fat map where all your app state lives [2] events and event-handlers - the only way of updating app-db is in an event handler, and you get to those by emitting events, which are just vectors with a keyword-id first element [3] subscriptions - re-frame views are just reagent views which source data from app-db using subscriptions. subscriptions are just reagent reactions with some registration, parameterisation and de-duplication stuff thrown in

maleghast12:11:42

@mccraigmccraig - 2 minutes into reading the re-frame README and I am saying out loud, to myself “Oooh, I LIKE this!”

maleghast12:11:46

Having Event Emitters and an Event BUS with subscriptions for “stuff” (State Change, Side Effects and UI Updates etc.) is a lovely pattern…

maleghast12:11:13

(At the moment I have onclick(s) that bind directly to cljs functions - this aspect of re-frame alone will really help)

mccraigmccraig12:11:34

it's not quite an event-bus/subscriber pattern - only a single event-handler will process each event

maleghast12:11:52

Yeah, but it provides a really nice separation

maleghast12:11:06

makes changing the targets of events a LOT easier for example

maleghast12:11:32

(I would imagine)

mccraigmccraig12:11:44

but yes, the separation is very nice, and it makes things quite testable - your subscriptions and event-handlers can even be tested in clj on the jvm (assuming you can stub js only deps) since they are mostly just munging pure ds

mccraigmccraig12:11:07

there's also https://github.com/denistakeda/re-posh - it swaps out the re-frame app-db map for a DataScript db. i've not used it so can't say how it lives up to its promises, but it sure looks intriguing

maleghast12:11:48

DataScript… @dominicm Haven’t you talked to me about this before..? Is it not a client-side DB that speaks DataLog..?

mccraigmccraig12:11:13

it is @maleghast - the point being that your app-db can grew large and complicated, and having an actual db to manage it might be appealing

maleghast12:11:09

*nods* Yes I can see that being very beneficial

maleghast12:11:52

I think I am going to want to add spec into this in order to have a definition for app-db…

maleghast12:11:25

…and that is a time problem, but I will get there…

maleghast12:11:45

right now__ I need to solve the map question, so that I am making progress in the eyes of my colleagues.

dominicm12:11:31

Someone in the office mentioned the idea of using datascript as a state management. It's an idea that's growing on me 🙂

maleghast12:11:05

Does anyone have a good recommendation for a clojure.spec primer - I ❤️ Rich and Cognitect for what they have given us, but their website and pages on their additions to Clojure are less-than-readable 😞

dominicm12:11:56

@maleghast do you need spec (I doubt it 😄)

maleghast12:11:24

@sundarj - Thanks for that; I have to be honest, right now I don’t want to have to cross over to Om. I know a lot of people that love it, but I’ve got a time constraint here… When I’ve got more time on my hands I will look at it, I promise.

maleghast12:11:51

@dominicm - Perhaps not, but the re-frame docs make a big deal out of having a spec for app-db and I can see why…

dominicm12:11:14

that's new I'd guess.

dominicm12:11:26

schema was the incumbent for that afaik

sundarj12:11:31

@maleghast we're all engineers here - stick with what works for you! that said, if/when you get the chance, i've been loving https://fulcrologic.github.io/fulcro/ (originally a sort of higher-level wrapper for om next, but in the upcoming 2.0 it's forking from it)

maleghast13:11:42

I’d be very interested in looking at that, in the fullness of time, aye 🙂

Rachel Westmacott13:11:27

Spec has some quite nice stuff, but I suspect it gets more useful for larger data structures - i.e. if you’re in a hurry you can probably do without it for now - it will be possible to add it in later

jasonbell13:11:36

@peterwestmacott I find it has it’s uses for smaller data structures too, especially when you are checking against streams of data in Kafka/Kinesis to see if the incoming message conforms etc.

mccraigmccraig13:11:23

similarly i find spec or schema validation of app-state great for even smaller apps @peterwestmacott - it saves you loads of time tracking down silly E_DYNLANG errors, and it's not much trouble to get going with

mccraigmccraig13:11:01

and i never take anything off a queue or accept an api request without schema checking it first

maleghast14:11:34

*nods* I can see all of that

maleghast14:11:54

I definitely need a better primer on clojure.spec than the http://clojure.org page on it in that case…

maleghast14:11:22

@jasonbell - The Kixi example just has me more confused I’m afraid - I did try__ to look at it… 😞

maleghast15:11:35

Anyone know what’s going on here:

var CLOSURE_UNCOMPILED_DEFINES = {};
var CLOSURE_NO_DEPS = true;
if(typeof goog == "undefined") document.write('<script src="public/edge.out/goog/base.js"></script>');
document.write('<script src="public/edge.out/goog/deps.js"></script>');
document.write('<script src="public/edge.out/cljs_deps.js"></script>');
document.write('<script>if (typeof goog == "undefined") console.warn("ClojureScript could not load :main, did you forget to specify :asset-path?");</script>');
document.write('<script>goog.require("process.env");</script>');
document.write('<script>goog.require("boot.cljs.main43971");</script>');

maleghast15:11:58

That’s what’s in my compiled JS instead of what should__ be there.

maleghast15:11:34

And thus, suddenly, my CLJS app has stopped working.

dominicm15:11:49

that's normal

dominicm15:11:58

that's what js looks like in dev

maleghast15:11:57

But I am getting a console error and my app is not initialising.

maleghast15:11:16

base.js:1357 Uncaught Error: Undefined nameToPath for react_dom
    at visitNode (base.js:1357)
    at visitNode (base.js:1355)
    at visitNode (base.js:1355)
    at visitNode (base.js:1355)
    at Object.goog.writeScripts_ (base.js:1369)
    at Object.goog.require (base.js:706)
    at dashboard:39

dominicm15:11:41

Your error message indicates that the js is actually right.

dominicm15:11:55

However, something is going on with reactDOM, that's for sure 🙂

dominicm15:11:03

I'm assuming base.js/visitNode is your own code?

maleghast15:11:32

Ah ok - well I’ve just tried to make some changes in my Reagent / React code, so maybe I’ve fixed it…?

maleghast15:11:03

OK, it’s the react-leaflet lib I was trying to use from CLJSJS

maleghast15:11:34

I’ve removed it and everything works again, but even having it in the require at the top of my code breaks my code

dominicm15:11:37

my first thought is to wonder if the react versions are different?

maleghast15:11:26

Might be it… 😞

maleghast15:11:42

Oh well, I guess I can try to use a non-react Leaflet library?

maleghast15:11:07

I’m just concerned about how I am going to inject maps in the middle of my React components…

dominicm15:11:57

what does it even do?

maleghast15:11:18

Leaflet is a map library for JS

maleghast15:11:37

The library I was trying to use React-ifies Leaflet

maleghast15:11:56

is the core library

dominicm15:11:12

so, a convenient maps wrapper?

maleghast15:11:36

And you do appear to be right… react-leaflet uses a later version of react than Reagent does.

maleghast15:11:43

(Clojars is helpful)

dominicm15:11:56

maybe a newer version of reagent could help? 🙂

maleghast15:11:14

Well, I’m on the latest version for stable… There is an alpha of 0.8, but I’m not thrilled about using non-stable code…

maleghast15:11:54

What I probably need to get my head around is how to use non-Reagent JS to insert something into a Reagent component

maleghast15:11:45

So that I can use the CLJSJS package for leaflet - which makes life very easy - and just push the map code into the component I am building, somehow…

maleghast15:11:53

Of course if that is not possible…

danm15:11:25

Heh. We had to use the latest Clojure alpha in one of our components to get the latest versions of the XML parsing stuff that had some functionality we needed

maleghast15:11:28

I am trying__ the latest Reagent…

maleghast15:11:43

It looks as though it should work with react-leaflet

maleghast15:11:15

So, if my current code works with the latest Reagent (0.8.0-alpha2) then I might be able to use react-leaflet…

maleghast16:11:39

OK, so my existing app works with the newest version of Reagent

maleghast16:11:52

now adding react-leaflet back in…

Rachel Westmacott16:11:48

Are you remembering to do a hard refresh in the browser periodiacllly

Rachel Westmacott16:11:05

that kind of thing (`Undefined nameToPath for react_dom`) can happen as a result of caching in the browser

practicalli-john16:11:57

I've updated the free workshop details on the day before ClojureX -> TicTacToe in ClojureScript, Reagent & SVG, followed by Understanding Transducers https://www.meetup.com/London-Clojurians/events/244060377/

dominicm16:11:57

in evil chrome you mean? 😄

maleghast16:11:00

OK, so I am clearly doing something Reagent-wrong now… react-dom.inc.js:17859 Uncaught Error: Attempted to update component NewClass that has already been unmounted (or failed to mount). at invariant (react-dom.inc.js:17859) at ReactCompositeComponentWrapper.updateComponent (react-dom.inc.js:4987) at ReactCompositeComponentWrapper.receiveComponent (react-dom.inc.js:4950) at Object.receiveComponent (react-dom.inc.js:11488) at Object.updateChildren (react-dom.inc.js:4293) at ReactDOMComponent._reconcilerUpdateChildren (react-dom.inc.js:10284) at ReactDOMComponent._updateChildren (react-dom.inc.js:10388) at ReactDOMComponent.updateChildren (react-dom.inc.js:10375) at ReactDOMComponent._updateDOMChildren (react-dom.inc.js:6357) at ReactDOMComponent.updateComponent (react-dom.inc.js:6171)

maleghast16:11:54

The Leaflet library I am using is no longer killing my app… but I am clearly not able to just [:> CODE HERE ] to insert a Leaflet map into my Reagent Component in the way that I did with my charts and recharts…

maleghast16:11:46

So… How do I use the library with Reagent..?

maleghast16:11:02

This will have to be my quest once I return from the pharmacy… Chicken Pox remedies are required for the Geeklings… 🙂

mccraigmccraig16:11:35

iirc you will have to create a type-3 component @maleghast and initialise the leaflet component in the :component-did-mount

maleghast17:11:07

I have NO idea what that means, but hopefully Google is my friend 🙂

mccraigmccraig17:11:13

oops, they are properly called form-3 components @maleghast - have a look here - https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components

mccraigmccraig17:11:24

(it's on the re-frame wiki, but it's about vanilla reagent)

maleghast17:11:37

Smashing stuff, thanks very much!

maleghast17:11:57

@mccraigmccraig so if I want to insert a form-3 component into my “main” component I have to list it as :componentWillMount ?

maleghast17:11:57

(in my main component)

mccraigmccraig17:11:06

no, the component is created by (reagent-create-class ... ) the :component-will-mount , :component-did-mount', :reagent-render etc are fns in the map given to reagent-create-class and become the react lifecycle methods

mccraigmccraig17:11:01

you can create a form-3 with only a :reagent-render method and that will be roughly equivalent to a form-2 component

maleghast17:11:17

Right, but if I want the map to appear “inside” a component..?

mccraigmccraig17:11:32

wrap the reagent-create-class inside a fn, and reference that in a hiccup vector

maleghast17:11:15

Sorry, yeah, it makes sense now 🙂

maleghast19:11:36

Don’t know if you are still around @mccraigmccraig, but does this ring any bells as to what I (may) have done wrong..?

Uncaught TypeError: Cannot read property 'getHostNode' of null
    at Object.getHostNode (react-dom.inc.js:11426)
    at ReactCompositeComponentWrapper.getHostNode (react-dom.inc.js:4787)
    at Object.getHostNode (react-dom.inc.js:11426)
    at ReactCompositeComponentWrapper.getHostNode (react-dom.inc.js:4787)
    at Object.getHostNode (react-dom.inc.js:11426)
    at ReactDOMComponent._updateChildren (react-dom.inc.js:10422)
    at ReactDOMComponent.updateChildren (react-dom.inc.js:10375)
    at ReactDOMComponent._updateDOMChildren (react-dom.inc.js:6357)
    at ReactDOMComponent.updateComponent (react-dom.inc.js:6171)
    at ReactDOMComponent.receiveComponent (react-dom.inc.js:6133)

mccraigmccraig19:11:18

no @maleghast i'm not sure what's going on there - i don't think i've seen that before

maleghast19:11:32

Ah well, never mind - thanks anyway 🙂

maleghast19:11:13

OK, I have proven to my own satisfaction that I am simply buggering up the Leaflet bit…

maleghast19:11:57

I’ve taken out the code I was trying to use to render a map and just put some text on the page and that works fine, so my form-3 component is all “correct” I guess.

mccraigmccraig19:11:55

there was a nice readme around somewhere about using non-react js components inside react, with some examples... can't seem to find it atm though

maleghast20:11:55

Thing is I am trying to use React stuff inside Reagent

maleghast20:11:51

Should I downshift to the plain version of LeafletJS, packaged for clojurescript (i.e. CLJSJS) so that my 3-form component is “rendering” non-react code..?

maleghast20:11:01

Sadly, it would appear that using “plain” Leaflet is not making any difference…

glenjamin21:11:51

do you have the code handy?

maleghast21:11:51

(defn re-leaflet
  [mapname lat long zoom]
  (let [mapdata {:foo "bar" :bam "baz"}]
    (r/create-class
     {:component-will-mount #(println "component-will-mount")
      :component-did-mount #(println "component-did-mount")
      :display-name (str "Leaflet Map - " mapname)
      :reagent-render (fn [mapname lat long zoom]
                        [:div
                         (str "This should be a map - " mapname)
                         (let [map (js/L.setView (js/L.map  "fakemap") {:position [lat long] :zoom zoom})]
                           (.addTo (js/L.tileLayer "https://{s}."
                                    (clj->js {:attribution "Map data &copy; [...]"
                                              :maxZoom 18}))
                            map))])})))

maleghast21:11:50

If I cut out the (let [map …) after (str “This should be a map - ” mapname) then I don’t get any errors. I am starting to wonder if I need to get the react-dom element to plug into the call to js/L.Map instead of using the id name as a string..?

mccraigmccraig21:11:01

@maleghast you are creating the map in your :reagent-render

mccraigmccraig21:11:30

you need to create the map in :component-did-mount and stash it until :component-will-unmount

mccraigmccraig21:11:55

as it is, you are creating a new map on every render

maleghast21:11:16

I see, so (def …) inside the function so that I can refer to the symbol inside :reagent-render ?

mccraigmccraig21:11:42

not quite.. here's an example of a form-3 component which interacts with the DOM https://gist.github.com/7b5bf934444fa8386c42856ebfc29173

mccraigmccraig21:11:20

it gets and stashes a reference to its DOM node in :component-did-mount ... in your case you would also create your leaflet map then

glenjamin21:11:56

think of if this way: :reagent-render creates the container node, and then the lifecycle methods perform imperative operations

glenjamin21:11:10

so render will be something like simply [:div], and then in did-mount you’ll grab a reference to the actual DOM <DIV> and mess with it

glenjamin21:11:34

if you want to change it over time, you’ll need to use did-update

maleghast21:11:59

@mccraigmccraig - Thanks for the gist - I think__ I understand it… 🙂

maleghast21:11:07

@glenjamin - Yeah, ok, that helps too…

maleghast21:11:22

@mccraigmccraig Definitely getting there now…

maleghast21:11:43

I have a map “window” on the page, just no actual__ map inside it…

mccraigmccraig21:11:02

make sure that the leaflet map creation is working ok by doing it by hand on your div first in the console

maleghast22:11:35

Erm, how would I do that @mccraigmccraig?

mccraigmccraig22:11:07

just follow through the leaflet map creation instructions in the javascript console, on a dom-node you have rendered in reagent (give it an id so you can locate it easily from the js console)

maleghast22:11:17

Yeah, I figured you’d say that…

maleghast22:11:28

I think I am pretty certain that my ClojureScript is wrong…

maleghast22:11:35

I have got the map appearing now…

maleghast22:11:50

(by doing just that)

maleghast22:11:11

Yeah, definitely getting there…

maleghast22:11:41

Getting down to it now… The params that are passed in at the top of the 3-form component definition are apparently not getting to the function.

maleghast22:11:44

I get “Uncaught TypeError: Cannot read property ‘lat’ of null” in the console, which is weird because that means that the first param is not causing an error…

maleghast22:11:42

Nailed it - Thanks EVERYONE, especially @mccraigmccraig