Fork me on GitHub
#re-frame
<
2016-02-24
>
hoopes01:02:33

hi, i’m trying to use highcharts with re-frame, so i’m using a form-3 component

hoopes01:02:41

(ns povon-cljs.views.main.content.section2.core
  (:require [povon-cljs.views.main.content.section2.chart-config :as cfg]
            [reagent.core :as r]
            [cljsjs.highcharts]))

(def Chart
  (.-Chart js/Highcharts))

(defn build-chart []
  (r/create-class
    {:display-name "build-chart"

     ; The div from :reagent-render should be in the DOM at this point, right?
     :component-did-mount
      (fn [this]
       (println "Component did mount")
       (Chart. cfg/chart-config)
       true)

     :reagent-render
      (fn []
        [:div#hc-bar.container
          {:style {:min-width "310px" :height "400px" :margin "0 auto" }}])}))

(defn section []
  [:section
   [:div.container
    [build-chart]]])

hoopes01:02:26

should the div from :reagent-render be in the dom when :component-did-mount runs? I’m getting the highcharts error where “the element is not in the DOM when highcharts is being constructed"

hoopes01:02:26

if i run the function after the fact from the js console, it works, so my thought is i’m doing something wrong in terms of timing

hoopes01:02:25

dammit, i knew it would be in the wiki. i’ll study that for a while. not sure how i missed it, i thought i read it all. thanks!!!

hoopes01:02:01

hm - isn’t that what i’m doing above in the recipe? reagent-render puts the div in the page, and component did mount does the highcharts construction?

hoopes01:02:25

i mean - isn’t the above pasted code equivalent to the recipe you linked

mikethompson01:02:02

Could the error be because you are doing this:

(def Chart
  (.-Chart js/Highcharts))

mikethompson01:02:10

Sorry don't know anythign about highcharts

hoopes01:02:16

er - did i miss the reagent/dom-node bit

hoopes01:02:31

haha, ok, no worries, i’ll keep digging - thanks for those two links

hoopes01:02:52

it’s obviously possible simple_smile i’ll get it

hoopes01:02:45

YES - cribbed from the recipe page. awesome. thanks again

lsenta07:02:21

@mikethompson: thanks for the advice, any way I can have have a piece of code subscribe to changes and update the db?

mikethompson07:02:15

I get asked this a bit. simple_smile The thing to remember is that ONLY EVENT HANDLER CAN CHANGE STATE (sorry for the caps)

mikethompson07:02:33

Which means we already know where any changes are going to come from

mikethompson07:02:45

From certain event handlers

lsenta07:02:04

I'm talking about a certain kind of event handler that uses a subscription instead of a "message id"

mikethompson07:02:10

We can then either: 1. add middleware like`onchange` on those event handlers 2. just use functions in the event handler

mikethompson07:02:26

Hmm. Event handlers don't use subscriptions.

lsenta07:02:52

@nberger: Thanks for the fix! Any reasons why that's not triggering an error (arity exception?)

lsenta07:02:36

Well, if I want to listen to change in some part of the db (active-module, auth, ...) and update state in other part (error, ask-for-login, ...)

lsenta07:02:00

That's still event-handlery, but on-change means I need to wrap every function changing the state

mikethompson07:02:04

In re-frame, events happen and then state changes. Before an event happens, the app was sitting quietly, in one state.

mikethompson07:02:34

It is your event handlers who mutate state. Which then triggers the Components to rerender this new state.

mikethompson07:02:48

So any "step forward" has to happen in an event handler

mikethompson07:02:26

In your code above, there had to be an event handler which updated the state .... which you want observed, right?

mikethompson07:02:32

So, if I;m understanding your correctly, you want an event handler to change some state. And then for other changes of state to be triggered as a result of that first change of state.

lsenta07:02:21

In that case that's fine, I have one place that changes this part of the db

lsenta07:02:17

I can wrap it

mikethompson07:02:33

alos consider the onchange middleware

lsenta07:02:13

yea that's what I meant with wrapping it

mikethompson07:02:27

We have to be slightly careful of things triggering, things, triggering things (complicated Signal graphs) because they tend to develop cycles and have "glitches".

mikethompson07:02:54

We want a nice unidirectional flow of data

mikethompson08:02:37

As an asside, part of what makes re-frame work so nicely is that all the changes you make in an event handler are revealed, to the rest of the logic, all at once (when the event handler returns the new db). There is no piecemeal updating of app-db. This is to avoid the problems associated with partial updates flowing through the Signal Graph.

lsenta08:02:43

I'm only supporting the idea of having events not being only arbitrary names but also paths in the db, or reactions/subscription

mikethompson08:02:20

When one change triggers another, triggers another, the system can be in odd states for some period of time, as the change ripple through.

lsenta08:02:22

That's does not complexify the signal graph (it'd tend to simplify it I believe)

lsenta08:02:40

That's not a problem solved by arbitrary events

mikethompson08:02:06

Righto. Tell me how you go with on-change

lsenta08:02:08

It's just harder to see the data structure, because instead of defining your operations on data you defined them on arbitrary names

lsenta08:02:38

Yea, I'll probably come back with a use case and a fork for db events

lsenta08:02:01

Thanks again man, it's very informative

mikethompson08:02:12

Righto. Thanks. Happy to talk further when you have somethng more concrete

leonid-shevtsov08:02:12

I have a question about testing. It says in the wiki that event handlers are pure functions. But they aren't - at the very least, they can dispatch other events. How can I test that an handler is dispatching other events properly?

mikethompson08:02:20

Perhaps you'll have to use with-redefs as described here (except in your case, you'll be redefing dispatch): https://github.com/Day8/re-frame/wiki/Testing#components---part-2b

mikethompson08:02:47

My concern is that the internal dispatch is perhaps done async?

mikethompson08:02:28

In effect, I'm worried that the with-redef will have ceased to exist, when the async dispatch happens (sometime later).

mikethompson08:02:11

But, for the record, I would push back on your claims. The vast majority of event handlers are, indeed, completely pure. If that's not the case, then you are doing something wrong.

jbaiter12:02:29

this might be a stupid question, but is it a bad idea to define a generic :get ks subscription that just calls get-in @db ks and a generic :set ks v handler that calls assoc-in @db ks v?

jbaiter12:02:29

that is, :get is just for un-materialised views on the application state

danielcompton18:02:17

@jbaiter: not a stupid question (there are none simple_smile ). We often take a middle ground where we have a handler for a section of the application, and then you pass a key to update the map in that section. For more complex updates, we'll write specific handlers

danielcompton18:02:14

For subscriptions, we sometimes do the inverse, 1 subscription to the root of an application section, then make a bunch of reactions from that one subscription, refining the data we want in the reaction

mccraigmccraig19:02:03

@jbaiter: and we do similar things to @danielcompton too

jbaiter19:02:46

thanks guys!