This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-07
Channels
- # announcements (1)
- # babashka (77)
- # beginners (219)
- # chlorine-clover (6)
- # cider (52)
- # clj-kondo (14)
- # cljdoc (5)
- # clojure (173)
- # clojure-europe (49)
- # clojure-finland (1)
- # clojure-germany (2)
- # clojure-italy (1)
- # clojure-nl (39)
- # clojure-sweden (4)
- # clojure-uk (51)
- # clojurescript (25)
- # code-reviews (9)
- # conjure (25)
- # data-science (2)
- # figwheel-main (6)
- # fulcro (74)
- # graalvm (1)
- # graphql (11)
- # jobs-discuss (17)
- # keechma (4)
- # lein-figwheel (4)
- # leiningen (1)
- # luminus (10)
- # malli (14)
- # mid-cities-meetup (2)
- # off-topic (28)
- # re-frame (5)
- # reagent (76)
- # reitit (30)
- # ring (7)
- # ring-swagger (1)
- # shadow-cljs (163)
- # spacemacs (11)
- # specter (2)
- # sql (43)
- # tools-deps (13)
- # vim (6)
- # yada (1)
Thank you @lilactown @victorbjelkholm429 and @juhoteperi, I'm using devcards, so a simple solution is to create a component to be added as the root of the card for each card. So when eventually an error occurs I'll know exactly it happens.
What’s the preferred way to bundle component css/sass while using reagent? I’m used to vue.js, where you can easily bundle css that properly scopes to your components.
Does vue.js encapsulate css using custom-element? I tried to do something similar recently, but I'm still using global css. Clojurescript doesn't have a good story regarding custom-element. But there are alternatives to compile the css and generate unique class names by component I guess. Is this kind of aproach you're looking for?
You can use webpack or other tool for processing sass and generating CSS and adding it to your index.html. But if you want scoped-css by component. You'll need to use a lib that does that like https://github.com/clj-commons/cljss, or maybe https://github.com/noprompt/garden.
In the company I work, we opted for using emotion (a JS library) inside clojurescript
@UBK8J929J yeah, vue.js does custom elements really well (imo). They have a custom file format (`.vue` ) in which you define the html template, component css, and custom js together and webpack handles breaking it apart later. vue.js has taken that approach that separation of concerns doesn’t mean separate files (like angular uses)
Thanks @URUTKFS0H I’ll look into those suggestions. I know I could also use something like BEM, but that doesn’t solve the component css problem (just the page css problem)
Does vue.js encapsulate css using custom-element? I tried to do something similar recently, but I'm still using global css. Clojurescript doesn't have a good story regarding custom-element. But there are alternatives to compile the css and generate unique class names by component I guess. Is this kind of aproach you're looking for?
Hi, I'm having trouble creating a component that has an internal atom that is derived from some external atom. I hope this illustrates what I'm trying to do:
(defn confirm-input [outer-atom]
(let [inner-atom (rc/atom @outer-atom)]
(fn []
[:div
[:div "Outer: " @outer-atom]
[:div "Inner: " @inner-atom]
[:input {:type "button " :value "inc-inner" :on-click #(swap! inner-atom inc)}]
[:input {:type "button " :value "inc-outer" :on-click #(swap! outer-atom inc)}]])))
(defn render [] [confirm-input (rc/atom 2)])
The inner atom initializes to the value of the outer, but it doesn't update when the outer atom updates. I'm sure I'm missing something obvious here. Anyone got any pointers?You want the inner atom to update when the outer atom changes? You are initializing the inner atom with the value of the outer-atom.
If you want a value that is syncronized both inside and outside a component you could use the same atom.
Thanks for replying to me!
(defn confirm-input [outer-atom]
[:div
[:div "Outer: " @outer-atom]
[:div "Inner: " @outer-atom]
[:input {:type "button " :value "inc-inner" :on-click #(swap! outer-atom inc)}]
[:input {:type "button " :value "inc-outer" :on-click #(swap! outer-atom inc)}]])
using the same atom doesn't fit my use case really. I want to create an input where the user has to confirm the change they're making
So I don't want it to update the application state until the user clicks confirm
(defn confirm-input [outer-atom]
(let [inner-atom (reagent/atom @outer-atom)]
(fn []
[:div
[:div "Outer: " @outer-atom]
[:div "Inner: " @inner-atom]
[:input {:type "button " :value "inc-inner" :on-click #(swap! inner-atom inc)}]
[:input {:type "button " :value "inc-outer" :on-click #(swap! outer-atom inc)}]
[:input {:type "button " :value "Confirm" :on-click #(reset! outer-atom @inner-atom)}]])))
That's very close to what I'm looking for, thanks, but do you know of a way to have the inner atom update if something else changes the outer atom?
Seems like reagent.core/track
could be useful as well, if the value comes from a function. Haven't really used track myself though, so not super sure it's applicable here.
Ok, I'll look into those, thanks for the suggestions!
cursor and track might be better options, but for this specific case you could
(defn confirm-input [outer-atom]
(let [initial-state (reagent/atom @outer-atom)
inner-atom (reagent/atom @outer-atom)]
(fn []
(when (not= @initial-state @outer-atom)
(do
(reset! initial-state @outer-atom)
(reset! inner-atom @outer-atom)))
[:div
[:div "Outer: " @outer-atom]
[:div "Inner: " @inner-atom]
[:input {:type "button " :value "inc-inner" :on-click #(swap! inner-atom inc)}]
[:input {:type "button " :value "inc-outer" :on-click #(swap! outer-atom inc)}]
[:input {:type "button " :value "Confirm" :on-click #(reset! outer-atom @inner-atom)}]])))
I ended up adapting JP's solution using cursor to give a reusable solution:
(defn shadow [atom]
(let [initial-value (rc/atom @atom)
current-value (rc/atom @atom)]
(rc/cursor
(fn
([_k]
(when (not= @initial-value @atom) (reset! initial-value @atom) (reset! current-value @atom))
@current-value)
([_k v] (reset! current-value v)))
[])))
I've got this example code in semantic-ui:
<Modal
trigger={<Button>Show Modal</Button>}
How do I do that in reagent?
Ah, yeah. I've already tried that.
I don't know what the { }
syntax is
given the error I also tried passing a fn reference, but that gives the same error.
reagent doesn’t do this by default because most of the time, if you pass a vector as a prop you actually want a vector
cool! thanks!
@lilactown that worked!
[:> Modal
{:trigger [:> Button "Show Modal"]}]
Maybe?I have an off-topic figwheel question. What's the best way of resetting figwheel if (reload-config)
doesn't do the trick?
lol... what if deleting the target directory and restarting figwheel also doesn't have the desired effect?
that's a tough one. Did you something in the environment you're running it in? Are you applying the change in the right project?
it's not reporting any errors and it appears to run when I make changes, so the file-watcher seems to be working. Only the code it produces looks like it came from an old source file.
@U051S9TAC what about warnings? Figwheel prevents doing any builds if you're getting warnings
Really? The basic luminus template code produces a warning but it compiled anyway.
I have one warning, not in my code - but on a dependency.
var: clojure.string/replace-with is not public at line 327 ... cuerdas\core.cljc
it should, at least. Might just not recompile the ns the warning comes from, not sure about that
I created the file and added {load-warninged-code true}
.
Then I ran (reload-config)
. Didn't notice any difference from prior behavior.
Short of copying my code into a new project I believe I'm stuck.
No idea where figwheel is pulling it's cached code from.
I'm trying to learn Reagent, and I'm trying to work on the concept of mutable data. It seems like you want mutable data in different pieces, so that each component can re-render separately, but you also want mutable data in one place so that your application is simpler. What's a good way to reconcile these two ideas?
how far do maps get you?
Maps?
The two ways I've seen it are to have a bunch of atoms scattered around the code, or have one giant atom that holds the entire state of the program.
The first option makes it difficult to track down mutable data, the second makes it so when the state changes, the entire webpage has to reset, rather than just the part that uses the piece of state that was changed.
I haven't tried it, but I suppose you could use a regular map of r/atom's eg
{:a (r/atom 1) :b (r/atom 2)}
(swap! (:a x) inc)
(deref (:a x))
That does make more sense... One map to rule them all. XD
in theory that would solve both problems, but I have no idea about the ergonomics - how reasonable it is in practice.
I'm not very used to working with atoms, so this part of reagent is very confusing for me.
@U051S9TAC, it seems practical; after all, it's kind of like inverting the atom of a map into a map of atoms.
My guess is that this leads to a worse development experience than scattering vars around your code. cljr-find-usages
is going to give you a lot of things you aren't interested in, for example.
But ymmv.
I find that tying state to components (using component local state) helps me manage many different sources of state
so e.g. if I have some form state, instead of putting that in a top level (def form-state (r/atom {:name "", :age ""})
I’d rather put it inside of a form
component and have that component pass it to each part of the form as arguments
(defn form
[_]
(let [form-state (r/atom {:name "" :age ""})]
(fn [{:keys [on-submit]}]
[:div
[name-input {:name (:name @form-state) :on-change #(swap! form-state assoc :name %)}]
[age-input {:age (:age @form-state) :on-change #(swap! form-state assoc :age %)}]
[:button {:on-click #(on-submit @form-state)} "submit]))