Fork me on GitHub
#reagent
<
2015-08-21
>
tel02:08:09

Is there a solution to the "side loading" of data in Reagent besides global variables?

tel02:08:58

I'm trying it now with dynamic bindings but that obviously blows up when a component gets re-rendered since the binding will have evaporated.

tel02:08:06

Sometimes people sneak data though the React parent context. I might be able to do it that way...

tel04:08:58

I am currently doing something like

tel04:08:25

(with-subscriptions [x a-state-query] [:h1 x])

tel04:08:29

expanding to

tel04:08:51

(let [x (do-query *state* a-state-query)] [:h1 x])

tel04:08:54

but every time there’s a component lingering there’s a chance that it won’t capture the global state

tel04:08:07

I could maybe use form-2 components

tel04:08:10

and expand to

tel04:08:01

(let [state *state*] (fn [] (let [x (do-query state a-state-query)] [:h1 x])))

gadfly36104:08:03

Both versions should work

gadfly36104:08:26

Assuming the do-query is responsible for the deref in each

tel04:08:23

hm? they don’t though

tel04:08:46

do-query does do the deref

gadfly36104:08:42

The atoms reagent atoms?

tel04:08:33

I’ll work with it a bit longer then see if I can make a minimal example

gadfly36104:08:28

Hmm I've done both, so I am not sure what is happening. Sweet, that sounds good!

gadfly36104:08:04

Well ive done what they expand to at least

tel04:08:22

The first render goes fine, but when I swap the ratom it gets the globally scoped value for *state* and dies on rerender

gadfly36104:08:41

(defn foo [ ] (let [x (get @app-state :bar)] [:h1 x]))

gadfly36104:08:22

Where (def app-state (reagent/atom {:bar "baz"})

gadfly36104:08:35

Is the most minimal example I can think of

tel04:08:58

but that’s not using dynamic scope

tel04:08:09

it just uses a global which I’m trying to avoid

gadfly36104:08:24

Ahh then I was missing the point

tel04:08:44

I think I left that out of my example, actually, haha

tel04:08:58

I’d like to be able to do something like

tel04:08:21

(reagent/render-with-state state [layout] node)

tel04:08:58

such that I can define my components, layout, without any pre-coordinated global references

tel04:08:07

the way I’m doing it now is

tel04:08:30

(binding [*state* {:baz “baz”}] (reagent/render [layout] node))

tel04:08:39

where layout looks a bit like

tel04:08:02

(defn layout [] (let [state *state*] [:h1 state]))

tel04:08:47

(binding [*state* (reagent/atom {:baz “baz”})] 
  (reagent/render [layout] node))

(defn layout [] 
  (let [state (deref *state*)] 
    [:h1 state]))

tel04:08:21

so that way the state is only ever local

tel04:08:42

*state* is just a reference to whatever local state is live during the first render

tel04:08:55

but that’s no good because reagent caches those computations

tel04:08:05

and later will call them without the binding wrapper

gadfly36104:08:46

I haven't explored anything like this before. Any one else got an idea?

tel04:08:10

in js land people work with react context

tel04:08:06

which is essentially solving the exact same problem

tel04:08:27

by knowledge that the virtual tree will be walked anyway

tel04:08:45

so they can hook context up from the top to the bottom

tel04:08:00

I guess I could write a hiccup walker...

tel04:08:21

but it’d probably be better to write a full react component that accesses the context like I like

tel04:08:39

and top it off with one too...

tel04:08:44

it’s also just really a reader monad… but there’s no composition of your hiccup forms, so, eh

benzen14:08:18

I've read almost all the code of reframe, but one thing is not quite clear to me, why the dispatch function use core.async?

darwin15:08:32

@benzen: event handlers can call dispatch during their execution, what should be app-db passed to them? it is easier to reason about app-db when only one event handler can be "in-flight” and its effects get committed to app-db, then next event is handled

darwin15:08:43

dispatch-sync is there for convenience I think, but it cannot be called from event handlers

benzen15:08:51

by the fact that we run on js with an atom in hand doesn't give us enought to be sure that there is only one event dispated at the time?

benzen15:08:09

*dispatched

darwin15:08:43

think about call stack, when dispatch is in flight, you can be somewhere deep building your next app-db, and in the middle you call another dispatch

darwin15:08:12

what should happen then? what app-db should be passed in that nested dispatch? what should be done with the result?

darwin15:08:26

if you need to call dispach within dispatch and you want it to be synchronous, simply call function which is implementing that inner event handler -you have control what app-db will be passed in and you have control how you incorporate the result

darwin15:08:52

potential observers of re-frame event queue won’t see that, they will just see one event dispatched (which did more complex work maybe reusing code from other events)

benzen15:08:22

at the moment the only case were i used a dispatch inside a handler was for ajax call, but i guess if i tryed to limit the concerns of my handler, i would end up wanting that dispatch use core async

benzen15:08:38

so thank you for the explanation