This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-22
Channels
- # bangalore-clj (6)
- # beginners (110)
- # boot (49)
- # cider (13)
- # cljs-dev (35)
- # cljsrn (5)
- # clojure (145)
- # clojure-conj (3)
- # clojure-dev (60)
- # clojure-italy (2)
- # clojure-nl (3)
- # clojure-russia (3)
- # clojure-serbia (1)
- # clojure-spec (116)
- # clojure-uk (58)
- # clojurescript (235)
- # cursive (14)
- # datascript (7)
- # datomic (31)
- # dirac (144)
- # emacs (1)
- # events (1)
- # hoplon (12)
- # leiningen (11)
- # luminus (60)
- # lumo (19)
- # off-topic (18)
- # om (74)
- # onyx (5)
- # pedestal (13)
- # precept (3)
- # re-frame (3)
- # reagent (15)
- # remote-jobs (7)
- # ring-swagger (25)
- # rum (1)
- # untangled (53)
- # vim (3)
Hrm, following this tutorial: https://github.com/Day8/re-frame/blob/master/docs/CodeWalkthrough.md but when I go to http://localhost:3449/example.html the app doesn't load, it just says "Reagent example app – see README.md"
@mattgeb the code walkthrough is just this example
is in the re-frame repo: https://github.com/Day8/re-frame/tree/master/examples/simple
You should be able to clone the repo and run it
BTW, there is a #re-frame channel
Oddly, there's an example.html file that was generated, and when I open that, it works 😕
Sounds like you are away
@qqq The lower function of this snippet is independent of rum: https://github.com/tonsky/rum/wiki/Mixins#keyboard-shortcut
I'm stuck how does one export cljs functions? Here is the equivelent js.
exports.hello = function hello (req, res) {
res.send('Hello World!');
};
I tried (set! (.-exports js/module) #js {:hello hello})
and (set! js/hello hello)
and (set! js/exports.hello hello)
. All are rejected.
(defn ^:export init []
;; can do one time init here
(js/console.log "app init"))
(defn ^:export start []
(js/console.log "app start")
(render (root) (dom/by-id "root")))
does it help in you case? https://github.com/thheller/shadow-cljs-examples/blob/6b96f52f4aa61388375d93852362417a7247a3a2/cljs-react-app/src/demo/app.cljs#L21-L27
Or maybe:
(aset js/exports "hello"
(fn [req res]
(.send res "Hello World!")))
https://clojuredocs.org/clojure.core/aset
advanced optimization won't rename methods defined in aset
Thanks @jiyinyiyong ! This worked (aset js/exports "hello" hello)
and there was no need to set the ^:export on the function and as far as I can tell the ^:export didn't work all by itself.
i guess ^:export
would only work in some cases, like :npm-modules
of shadow-cljs, or other case compiling to npm modules
@jiyinyiyong :node-library
is what you want, never mess with js/exports
:npm-modules
is meant to work with JS tools .. like webpack
, create-react-app
or just node directly
:node-script
is for things you run yourself, so not something that is included somewhere else
any node.js experts around? is there any way to tell why a node.js instance doesn’t exit? I have a process that doesn’t exit but I closed everything and there shouldn’t be anything left running
hmm, any chance to get at that remotely? If I have anything connected to the process that will be amongst the things keeping it alive 🙂
yeah or maybe like a setTimeout
it’d keep it too, but it’s happening anyway
This article talks about passing entire app state to components in Om Past https://circleci.com/blog/why-we-use-om-and-why-were-excited-for-om-next/
What I don't understand is, wouldn't this violate the react concept, and force re-rendering of all components even for small changes to data that components don't need?
Hi, Calling PropTypes validators directly is not supported by the prop-types package. Use PropTypes.checkPropTypes() to call them.
Anyone dealt with this in Clojurescript?
Actually scrap that... Looks like my problem is actually this error:
Uncaught Error: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's render method, or you have multiple copies of React loaded
I've seen that issue
it's probably correct that you're using multiple versions of React in the same program
wild guess: some cljsjs dependency erroneously includes its own React due to Webpack fail
@dealy what do you mean push stuff? You cannot just push to one or the other and expect interleaving. You must have two Async loops running. Is that what's happening?
> npm ls react
[email protected] /Users/crankyadmin/code/Personal/testapp
└── [email protected]
ah you're using your own version of react using npm?
have you seen https://github.com/pesterhazy/double-bundle ?
> npm ls | grep react
├─┬ [email protected]
│ ├── [email protected]
├─┬ [email protected]
│ └─┬ [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
├── [email protected]
├─┬ [email protected]
No I haven't, taking a look now 👍:skin-tone-2:
@crankyadmin I've written a draft blog post on this topic, which may help as well: https://github.com/pesterhazy/presumably/blob/master/posts/double-bundle.md
check your clojurescript dependencies (`lein deps :tree`) to see if any depend on cljsjs/react, cljsjs/react-dom or cljsjs/react-server
plus some cljsjs dependencies accidentally include react (see this issue: https://github.com/gadfly361/baking-soda/issues/3#issuecomment-304524921 )
ah yes, reagent is depending on react.
Which side is it better to exclude from, lein or npm?
I'd argue, lein
Do I need to do some magic with the namespaces then?
yes, check this diff: https://github.com/pesterhazy/double-bundle/compare/init...master#diff-5ef6b69d264f786c496e5b32b71dcea7
@ajs As far as I understand, there're two slow stages in React: calculation of DOM diff and applying actual DOM changes. If you have ClojureScript react wrapper then also add "interop stage" into the mix (e.g. conversion from Reagent's Hiccup-like datastructure into JavaScript React components). But even with a single app state you can avoid doing most of costly recalculations thanks to ClojureScripts's fast comparisons of immutable data passed into smaller components: if the piece of data passed into the particular component is the same then React wrapper will quickly bypass the whole component "recalculation" (https://facebook.github.io/react/docs/optimizing-performance.html#using-immutable-data-structures). But to take advantage of such optimisations you need to understand what can trigger recalculation of the particular component in the React wrapper of choice. I'm not sure about Om and can only point to a nice explanation for Reagent: https://github.com/Day8/re-frame/wiki/When-do-components-update%3F Maybe there's a more thorough explanation somewhere on the web, because the same question can also be applied to JS frameworks with a single state, such as Redux.
@metametadata thanks, I've got some reading to do
Fair dos, cheers pal 🙂
hope it'll make you a bit less cranky
@pesterhazy It was because I was loading multiple copies of react 😳
Removed the dup and added the namespaces in and everything works as expect. Thanks again for your lead!
sure thing
Hi, in a simple compojure get route, I need to call an async function and return the result of that callback as a response
compojure itself only does route matching; whether (and how) or not your handler can return an async response rather than a plain Ring response map is up to your HTTP server (jetty, httpkit, immutant, etc.)
Depending on what the function does and why it's async, the easiest (though probably not best) thing to do might be to just wait for it to finish
though keep in mind that that would hold onto one of your HTTP response threads, which again may or may not matter depending on your HTTP library
@dnolen when I said push stuff I mean that messages arrive from the server and are added to the channel that the publication was created on. And yes there were two loops running, the looper function was called twice in the example I gave yesterday.
@dealy but then recreating the problem so that a 3rd party can confirm should be trivial no?
@dealy but based on your followup comment it seems like there might be a bug in the code or a problem with expectations
@dnolen sorry, I'm not understanding your suggestion. In my example all messages are pushed on to the same channel. the async loops pull from separate channels
yes, that's what I've been trying to get clear all along, I was originally just wanting to talk with someone to see if my understanding of how this was supposed to work was correct
I'll try to make something small that exhibits the same behavior, of course it probably will just work correctly when I first put it together.
@dealy I looked backed what you wrote, I just don’t understand “calling of the functions … aren’t really interleaved”
just that there are gaps also for instance If my servers sends m1 m2 a1 a2 m3 a3 m4 a4 a5 my handlers are only getting m1 a1 m3 a4
(that sounds like a separate issue which should talk about separate, I just suspect a bug in your code)
that is what I was curious about, am I working outside of the expected limits of messaging by pushing too much too fast
"gist" is a github feature that allows you to share a single file without having to create a full github repo; you can also use something like http://pygments.org or codebin or, well, really anything that lets others see the full example
dealy: http://pygments.org/demo/6625943/ inspired by your code above seems to have the expected behaviour to me
calling (run)
gives me
-+-++--++-+-++--+-+-+-+-+-++--+-+-++--+-+-+-+--++-+-+-+-+-+-+-+-+-+-+-+-+--++-+-+-+-+--++-+-+-+-+-+-+--+++--+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++--+-+-+-+-+
which seems properly interleaved
@dealy I took @gaverhae’s snippet and added a 100 ms delay between writing to the pub chan and I could not replicate under Node.js - my interleaving looks the same as on the JVM
@dealy https://gist.github.com/swannodette/dee03ccb778f53fa1564e553bfd080d5 is the exact code I used
yea, so far I haven't been able to make a small standalone example which demonstrates the problem, I thought something like this might happen
The layout that @gaverhae used looks basically correct, except that I have been using >! and <!
dealy: put!
is non-blocking whereas >!
is blocking, which may explain the behaviour you observe: if the producers get blocked that may be the reason you don't see the interleave.
@peeja i'm curious, if the point of react is to avoid rendering components unnecessarily, what is the point of using the old om at all if you're forcing all components to always re-render even if they don't need it?
@dnolen one thing that is also different is that in my handler functiions I'm updating an atom which triggers a reagent component refresh
I'm confused why reacts page on dom elements doesn't actually list all the supported elements, only supported attributes within the elements. Does such a list exist anywhere? https://facebook.github.io/react/docs/dom-elements.html
@dealy that doesn’t seem significant to me, but I would definitely say the issue does not seem to be core.async but something higher level in your application
@ajs Well, it worked well for a while, and then we found we had to pass the entire app state around most of the time to do anything interesting. We didn't anticipate that being an issue going in.
It's also not as bad as it sounds: any change to the app state requires all of those components to re-render their virtual DOM (and run lifecycle methods), but if the rendered virtual DOM stays the same, React still saves us the cost of making any changes to the real DOM.
@peeja I've noticed that the term "render" can mean one of two things: the "calculation" for a component's content, and the actual rendering in the Dom. Re-render often doesn't actually mean a Dom render, despite how it sounds, as you point out.
@ajs (Replying to this rather late 😛) While you're right, FWIW, in my experience "rendering" in React can pretty much always be taken to mean the process that calls the render
methods, not the process of updating the DOM (which is usually described as "reconciliation", although I think properly speaking the reconciliation process includes calling the render methods too. People generally just don't talk about the DOM updating much in React because it's so well abstracted. 🙂
yet, the actual updating of the DOM is the real costly piece, and where the actual onscreen rendering happens, so it can be a bit confusing as to what "render" means but thanks for pointing out the most common use of the word
@dnolen yea, I didn't really expect that there was a bug in core.async. But that there was some issue relating to it or cljs that I'm not understanding.
@dnolen maybe something about the singlethreaded nature of javascript? All of the puts to the bus happen as Sente receives events over a websocket from the server. I assume that sente is putting multiple events on the bus while the looper can be off in the event handler and then when the looper finishes and calls <! those events should be waiting in the channel. But it seems like often those events are just lost and looper doesnt' respond until the next event arrives
the most plausible explanation there is that there’s something reading the channel that you forgot or didn’t intend
@dealy I agree with @noisesmith
losing stuff doesn’t make any sense unless you’ve specified those semantics on the chan
you constructed
Sente doesn't call put on the bus itself, it calls a handler I wrote which in turn puts on the client side bus
one thing that might help with the debugging is to change (chan)
to (chan 1 (map (fn [x] (println "processing" (pr-str x)) x))
which should confirm the messages that actually go through the channel without altering behavior
*fixed
where would you store app state when application goes offline? atom? datascript? - I need to have couple of records downloaded on page start - user does changes offline, this changes need to be synchronized - user almost never uses 2 devices which can be offline, conflicts are unlikely - all dataset are basically some 3-4 database tables, couple of megabytes common, tens of kilobytes per user
@jiri.knesl would the localstorage api work for you? https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage - it’s easy to use from cljs
as a framework I prefer re-frame, but I guess it isn't important
unlike session storage, local storage persists across tabs
@noisesmith I know about localstorage, just if you would save atom, or datascript synchronised in local storage
well, atoms aren’t data, they are stateful objects, but I use transit to serialize data that gets copied into my state atom
not the whole state, just the parts that need persisting
I understand
so atom + hashmap + transit for sync
that’s what has worked for me, yes
+ some delta database I will use to know what to sync
I think event-sourcing in clj+cljs would make all this izomorphic
oh, so you could even store the event series as localstorage indexes, and then you know you have more to load when more exist
(plus bundling up state occasionally for efficiency that’s a typical event sourcing thing iirc)
thank you
@noisesmith yea, I had done something like that yesterday. but I was looking for exceptions not sure if I printed anything out
@dnolen @noisesmith here is some of the log output that shows the behavior I'm experiencing. Notice that there are many >! values that don't have corresponding <! messages: https://gist.github.com/dealy663/f95caef8806da76bec724a59e520f3c9 If you feel like taking a look
only if you think it needs an inline preview
@dealy they are getting put on the chan weirdly out of order, which makes me think it’s happening in a callback that is waiting on some other callback, that might take an indeterminate amount of time, and perhaps simply not get called?
that’s kind of speculative though
I wouldn’t expect things to get that out of order without some other async factor in the middle that potentially goes wrong…
no, the puts are in order notice that there are received and cooked puts which correspond to ev1 and ev2 in the previous examples
@noisesmith I added your xform to the sub channels and they are only showing up in direct correlation to the updating received/cooked blob messages. This is so weird, I can't find anything else taking off of these channels
@jiri.knesl: if you're thinking about persisting a datascript db to localstorage you might want to check out https://github.com/tonsky/datascript-transit which makes it pretty easy. There's also https://funcool.github.io/hodgepodge/ which is a nice clojureish interface to the API, and another few projects which are linked from that page
@timgilbert thanks! I will look into it
@timgilbert there is some trigger "on-change" on this hodgepodge?
@souenzzo: not as far as I know, but you could use regular js event handlers for that, eg https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Responding_to_storage_changes_with_the_StorageEvent
I've never tried it, I've just used localStorage as read/write storage
There's also https://github.com/alandipert/storage-atom which lets you add a watch to localStorage
I'm trying to write a macro in cljs that collects a set of defns into a hash-map with keywords matching the function names as keys. For some reason the macro works when I run it directly from the repl, but not when it is used in the source files; is there a difference between the return value of defn in the repl vs in compiled code?
I use storage atom. It's awesome. And has this callback. But I have no idea how to operate in a functional way without a "on-change" trigger
I may be tired but it looks like reify
doesn't compile inside core.async
's go
:
(defprotocol Foo)
(go
(reify Foo))
Here's the minimal example with the error message I get in readme: https://github.com/metametadata/cljs-go-reify-bugOK, it seems to be officialy not supported: https://dev.clojure.org/jira/browse/ASYNC-57
@shader I think I did something similar in a macro, using cljs.analyzer.api/ns-publics
to find the specific functions in current ns: https://github.com/metametadata/clj-fakes/blob/ede68f97dacbef11a881e701977e75d560c16bac/tasks/core.cljc#L46
but simply loading it in the browser returns {nil <last fn in group} instead; I presume this means that all of the name metadata was stripped during compilation
and what is the example usage? I mean, how does the invocation of the macro look like?
before, I had simply been defining the events object with (def events {:load-messages (fn ...
, but using defn first seems like it would be easier to test, and the fact that it returns vars should make it more reloadable as well
I could have collect
walk the defns and just grab the 2nd element for the name I guess, if it really is the metadata that's the problem
I see, that's now much more clear. Although I can't comment much about if the end-goal, I'm trying to think why the provided macro misbehaves.
Isn't f#
just a form though during the macro expansion? This would explain why there's no :meta in it.
i.e. I guess the first f#
will contain the data structure of (defn load-messages [db [_ {:keys [messages]}]](assoc db :messages-list messages))
aah, no
I misinterpreted the macro
but it would fail if name is not the second element I suppose
don't know why I didn't think of that the first time... reaching for post-compilation metadata is a much more convoluted approach
not often, e.g. if you decide to add ^:no-doc
meta
nope 🙂
@metametadata thanks for your help!
@shader no problem 🙂
@shader ah, right, ClojureScript would not even create a Var, it compiles defn
into load_messages = (function ... (..) {..});
at least, I think if it used the var it would update the reference when the function was redefined
I have another solution though; I'll just have the reload function in my core js file update all of the hash-maps; probably better than relying on implicit reloading anyway
suppose I have a vector of namespaces [a b c], and I want to get the values [a/events b/events c/events]?
it's shouldn't be possible, as there're no vars during runtime
but in Clojure it is doable: https://clojuredocs.org/clojure.core/ns-interns
that would give you compilation time information - var names, etc.
I suspect that may not work after the advanced compilation
because of name munging, you should test it though
you can ensure it survives with ^:export
though
oh, pardon I didn’t read the scrollback
I have a suspicion that namespaces are being used where hash-maps would be a better fit
ns are not good data structures
not even in clj, but it’s worse in cljs