This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-21
Channels
- # announcements (1)
- # babashka (13)
- # beginners (85)
- # calva (1)
- # chlorine-clover (16)
- # cider (30)
- # clj-kondo (2)
- # clj-on-windows (5)
- # cljdoc (3)
- # cljs-dev (12)
- # cljsrn (19)
- # clojure (88)
- # clojure-europe (39)
- # clojure-nl (7)
- # clojure-sweden (3)
- # clojure-uk (8)
- # clojurescript (35)
- # core-async (3)
- # data-science (2)
- # datomic (17)
- # defnpodcast (3)
- # deps-new (1)
- # editors (18)
- # emacs (4)
- # events (1)
- # expound (1)
- # figwheel-main (8)
- # fulcro (9)
- # graalvm (2)
- # graalvm-mobile (11)
- # helix (44)
- # jobs (7)
- # lsp (95)
- # luminus (9)
- # malli (6)
- # meander (4)
- # membrane (2)
- # missionary (13)
- # off-topic (98)
- # pathom (2)
- # polylith (4)
- # portal (3)
- # re-frame (6)
- # reagent (27)
- # reitit (3)
- # releases (3)
- # remote-jobs (6)
- # rewrite-clj (1)
- # rum (2)
- # sci (3)
- # shadow-cljs (7)
- # sql (66)
- # tools-deps (80)
- # vim (5)
- # xtdb (3)
Hi! How do you write compound components in Reagent?
I thought it would be [:> Root AlertDialog.. etc]
but no luck
AlertDialog.Root
is just a JS field access.
A proper way would be (.-Root AlertDialog)
.
wow perfect
There are a few ways fo achieve this depending on what you’re looking for:
[:<>
[child ...]
[child ...]
[child ...]]
but then if you wanted your component to just accept children without the need to use a fragment:
(defn parent-component
[props & children]
(into [:div props] children))
[parent-component
{...} ;; props
[child]
[child]
[child]]
Note that I added props
as the first arg of parent-component
: this is a style preference I have when writing components. You can omit that if you like.thanks thomas! but not sure if this was what i needed.
turns out i just had to write (.-Root AlertDialog)
.
Anyone know what translating this into cljs looks like?
<CountdownCircleTimer>
{({ remainingTime, animatedColor }) => (
<Animated.Text style={{ color: animatedColor }}>
{remainingTime}
</Animated.Text>
)}
</CountdownCircleTimer>
I think it should be
(def text (r/adapt-react-class (.-Text ReactNative)))
(def countdown (r/adapt-react-class CountdownCircleTimer))
[countdown
(fn [^js props]
(let [remaining-time (j/get props :remainingTime)
color (j/get props :animatedColor)]
(r/reactify-component
[text
{:style {:color color}}
remaining-time])))]
but that doesn’t work, I’ve tried many combinations of things that I think should work but nothing does and I’m not getting any useful errors back, possibly because I’m in react-native land and the quality of errors tends to go downhill a bit thereThis is the component I’m trying to use https://github.com/vydimitrov/react-countdown-circle-timer/blob/master/packages/mobile/src/components/CountdownCircleTimer.jsx
Its expecting ‘children’ to be a function that returns a Text react component, but I’m pretty sure thats what I’m doing 🤷
I’m thinking its because of whatever reagent generates, its not compatible for whatever reason
Also, your JSX example uses Animated.Text
but the CLJS code uses ReactNative.Text
. Maybe it's important, dunno.
Ok I figured out I can run react native stuff in web mode and then get errors in the console. So with my first example (reactify-component)
Functions are not valid as a React child.
With as-element... it worked.. now I feel embarrassed, I was sure I tried that Out of interest, is there a better way to write it? It seems I'm going from react component (.-Text animated) to reagent component with adapt-react-class to react again
Depends on metrics you use to decide if something is better or not. That above is pretty much idiomatic Reagent code, although I'd probably use direct JS interop nowadays instead of j/get
, especially given that you already use ^js
.
Another way would be to create a React element yourself - then you would not need to use r/as-element
and (def text ...)
.
Yes bad habit of mine to use j/get, ok I will look into how to create React elements manually. Thanks for the help btw, much appreciated
Hi there! I'm doing a quite complicated code that allows users to define, with hiccup, their own reagent views. The problem is that I need to catch errors, any anything I'm doing is still leaking errors to console, etc... Do anybody have any tips on doing this? I'm quite on a lost here...
So far, I tried error-boundary
but it fails if the hiccup itself is invalid for example, if a [element {params...}
throws an error
I also tried render-to-string
around a try-catch, but it also fails
A little bit more info on this: Seems that if I use:
(let [old reagent.impl.component/wrap-render]
(with-redefs [reagent.impl.component/wrap-render (fn [ & args]
(prn :args args)
(try
(apply old args)
(catch :default e
(prn :error e))))]
I can catch the error. Is far from ideal.... but it works. Any tips on making this better? 😄Nevermind.... on a "real world scenario" it also doesn't work (I believe because it's async). I'm quite on a lost here on what to do... I'll try to get a minimal example and post here, and see what can be done
Ok, after lots of trying and poking on the internals, I can somehow make a "try-catch" for Reagent renderers that works for my case - but it "monkey-patches" wrap-render
in some way.
Not sure if there's a better way, but these are the lines I changed: https://gitlab.com/clj-editors/repl-tooling/-/merge_requests/3/diffs#diff-content-5c606df7924556558908352ff1671bf3de7b9fcc.
I hope I can somehow find a better way to solve this issue, because I don't think it's a good solution, really, to the problem I have to solve 😅
an error-boundary should work as long as there's a component between what throws the error and the boundary
i.e.:
;; doesn't work
(defn my-component
[]
[error-boundary (throw (ex-info "Oh no!" {}))])
(defn root
[]
[my-component])
;; does work
(defn my-component
[]
(throw (ex-info "Oh no!" {})))
(defn root
[]
[error-boundary [my-component]])
Nevermind.... on a "real world scenario" it also doesn't work (I believe because it's async). I'm quite on a lost here on what to do... I'll try to get a minimal example and post here, and see what can be done