This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # aws-lambda (3)
- # beginners (57)
- # boot (3)
- # bristol-clojurians (1)
- # cider (38)
- # cljs-dev (23)
- # clojure (35)
- # clojure-italy (32)
- # clojure-nl (6)
- # clojure-spec (35)
- # clojure-uk (132)
- # clojurescript (34)
- # cursive (22)
- # data-science (1)
- # datomic (54)
- # devcards (1)
- # duct (5)
- # editors (7)
- # euroclojure (4)
- # fulcro (40)
- # graphql (1)
- # hoplon (6)
- # immutant (5)
- # jobs (1)
- # off-topic (22)
- # om (1)
- # planck (17)
- # portkey (1)
- # protorepl (12)
- # re-frame (97)
- # reagent (67)
- # reitit (16)
- # ring-swagger (1)
- # shadow-cljs (98)
- # spacemacs (8)
- # sql (20)
- # tools-deps (60)
@bravilogy it's been an age since I looked at secretary but my guess is the goog.History example in the readme might help guide you as to how that should all come together.
It seems like the process is: 1. change uri 2. navigation event triggered, dispatch! called... secretary route invoked.
You can use a named route to buid the URI: https://github.com/gf3/secretary#named-routes
Funny that they don't give an example of setting the browser uri programatically to start the process. Something like
(.setToken h uri) should do the trick.
Getting familiar with goog.History will help: https://google.github.io/closure-library/api/goog.History.html
At the risk of posting a bleary-eyed, under-caffeinated Monday morning muddle, I’ve got a style question. Consider the following 2 components:
I’ve always written the former, but it seems like the latter is a lot more concise, and I think it’s pretty common that a subscription is only used once in a component. Thoughts?
(defn component-1  (let [foo-sub (rf/subscribe [:my-foo])] (fn  [:div "My foo" [:div @foo]]))) (defn component-2  [:div "My bar" [:div @(rf/subscribe [:my-bar])]])
Nothing wrong with either ... but component-1 is slightly old-school these days and I'd be tempted to use a slight variation on the 2nd. First I'd consider using "Lambda Island Naming": https://github.com/Day8/re-frame/blob/master/docs/SubscriptionsCleanup.md#lambdaisland-naming--lin Then
(defn component-2  (let [meaningful-name (<sub [:my-bar])] [:div "My bar" [:div meaningful-name]])
1. I have a preference for using LIN because it removes the possibility of forgetting the
@ (which gets everyone sooner or later)
2. I kinda like having the subscription in a
let to make is clearer. But that's just me.
I'd suggest avoiding lets if the subscription keyword is clearly named. Of course in a function that small it's pretty obvious what's happening in any way, but generally everytime I see a let I start thinking "Ok, where are the other places this binding is referred to"
Does anyone have time to help a clojure / re-frame beginner understand how to tie changes on the web page back to the database?
Also I need a bit of help understanding how large / small a view should be. Right now i have one large main-panel function 🙂
So far I have the page rendering and data is bound from the database to the page so that I see what I expect. I just don't know how to have changes on the page update the database so it can be reflected by the other subscriptions.
It's a single page app with one view that just generates a few URLs and shows them on the screen based on the form input.
Right i'm just so new to both clojure and re-frame I'm having a hard time with the examples / documentation.
reg-event-db to register an event handler, which is a function that takes the current state of the database, and a vector of arguments, and returns the new/updated state of the database, usually via
I just want to have a form field, update a location in the database so that other areas subscribed see that data.
Ok, do you have a specific field you’re working with right now? Might be easier to use examples that map directly to what you’re currently working on
Right. The basic idea is that all your GUI front-end stuff ever does is to fire events, and then the event handlers worry about what to do with it
So for your input field you’ll just define an
on-change handler that does
#(re-frame.core/dispatch [:helpdesk/update-incident-number (-> % .-target .-value)])
The last part of that vector is just pulling the current value of the text field out of the JS event.
Also, I like to use namespaced event names to organize my events, so all the events that have to do with the
helpdesk form, I’ll call
Right, and your event handler will define a function that looks something like this:
(re-frame.core/reg-event-db :helpdesk/update-incident-number (fn [db [_ new-incident-number]] (assoc-in db [:helpdesk :incident-number] new-incident-number))
The first argument your handler function will get is the current value of the app-db
The second argument is the event vector that you passed to
re-frame.core/dispatch. We use underscore for the first value inside that vector because we already know it’s going to be
:helpdesk/update-incident-number. That leaves the second value as the one we’re interested in, and it’s the new value for the incident number.
Is there any consensus about when – if ever – to use plain old Reagent atoms in re-frame apps? I started out using atoms for all sorts of short-lived local state, like dialog contents and animation state, but I've gradually changed to using the app-db for everything. This somehow feels cleaner and makes tools like re-frame-10x more powerful, but having to mess with the app-db, events and subscriptions for every little thing I add to some dialog is sometimes annoying.
We were just talking about this at work. My experience has been that if you have a component that has a bit of state that (a) is of no interest to any other component or handler (b) is not part of any application data and (c) needs no validation or other processing, then a local
ratom is fine. My other experience has been that it’s not uncommon to put state into a
ratom and then later discover whoops, this other component/handler DOES need to access it. But it’s really easy to re-factor.
write your local ratom state as if it was a slice of the database, then refactoring in the future is really simple… for example use a single map instead of multiple ratoms
My canonical example is I have a popup or drop-down or something that needs to track open/closed state. It’s fine to put that into a
ratom (until you decide that you want it to automatically close when you click some other component 😉 )
I sometimes look at these close calls from the standpoint of self-documentation, specifically that using the db for purely local state is like false advertising that the state is anything other than local. My2c.
@tord personally, I put all state into app-db and don't use local reagent atoms. I feel like when bugs happen in local reagent atoms, it is easier for them to be less visible.
I have a newbie question about working with CIDER and re-frame in a brand-new SPA project
My expected pattern of work in CIDER (with backend code) is to visit a file,
C-c M-n to put the REPL into the file’s namespace, then
C-c C-k to load the file, and
C-c C-e to eval forms as I add them to my source file
I have a project I’ve created with
lein new re-frame ion-client +cider +aliases and I have used
cider-jack-in-clojurescript to get a cljs REPL
I can do stuff like
(js/alert "yo") and see that work, and if I make changes to the “starter” app-db and reload the browser pointed at
localhost:3449 I see those changes
but if I try to “load” any namespace that
requires another one of the project namespaces, I get an exception that the namespace doesn’t exist
so for example in
(:require [ion-client.db :as db] ...) and when I
C-c C-k that file I get a stacktrace that leads off
namespace ion-client.db does not exist
so clearly I’m doing something wrong here but I don’t know if it’s trying to
C-c C-k at all in a Figwheel-y world, or if my REPL setup is wrong, or what. Does anyone read what I’ve written and immediately think “oh man, that poor fellow has misunderstood
thing“? , by chance? 😇
Hey Chris! You may be able to get your setup working the way you are trying. What I do that’s a little different is run
lein figwheel or
lein dev from the command line then from Emacs run
I’m always seduced by the cyberpunk hipness of
*-jack-in but it seems common that you want to run your REPL outside and just
connect to it. 🙂
Yeah, it depends upon what you want. For most of my workflow figwheel’s auto-compile-on-save is good enough for me, I’ll write some code, save, then do something in the browser to execute it. When I do want to connect emacs to a running REPL I’ll run
cider-connect, however that means I need to have an nREPL server running. I know I have that in some projects, however I don’t think it comes for free with the lein template you just ran.
For the way I suggested you need piggieback. If you follow the installation instructions here: https://github.com/nrepl/piggieback you’ll get an nREPL server that you can
@chris_johnson I think it's that CIDER doesn't know about the cljsbuild source paths. Try adding
src/cljs or whatnot to the top level
:source-paths vector and restart the REPLs
what do you all think it would take to allow re-frame to be used with frameworks other than reagent?
@lilactown re-frame is about 600 lines of code, so a variation for another framework is not too hard. For example, there's citrus for Rum.
(But I personally do not like many of the decisions taken in citrus ... eg use of multi-methods, rather than "reg-*").
e.g. I’m working on a hiccup compiler + some other libs that provide similar functionality to reagent without having a custom render queue or runtime interpretation of hiccup
in a sunshine, rainbows & unicorns world a re-frame app could swap out reagent with the bundle of libs I’m creating and it mostly JustWork(tm)
@lilactown You might find this discussion interesting then?: https://github.com/reagent-project/reagent/issues/271
yeah, what I’m interested in is providing a set of libs that are quite a bit simpler than reagent, architecturally
but I think that providing a higher-level library that combines them into something as powerful as reagent is necessary. and providing the ability to use with re-frame (which has become a de-facto standard almost for many new projects, a la Redux) would just be awesome
it looks like there’s a few places where re-frame hooks into the reagent render queue which might prove to be complicated to polyfill
@lilactown I don’t think plain re-frame is hooking in to reagent, bar the tracing for re-frame-10x?
hrm. I see that router.cljc at least brings in
reagent.after-render and is doing some tricky async event dispatching
I’ll have to spend some time digging into it more and actually understanding how re-frame works better
typically you’ll add that to an HTML file with a <script> tag, as well as add any CSS that your app needs to that same HTML file
@lilactown thanks, that's what I was looking for. I thought I had tried that already, but I guess not.
typically cljsbuild projects have a “dev” build which isn’t optimized and has some developer tools added into the mix, and then a “prod” build or what-have-you that runs advanced compilations