Fork me on GitHub
#clojurescript
<
2023-05-30
>
souenzzo00:05:24

Is there a coverage tool for cljs?

Somi Cho14:05:07

you mean for tests?

byrongibby07:05:30

Hi, is there any way of accessing the JavaScript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments from a ClojureScript function? I need to implement gtag.js in ClojureScript which requires the use of the arguments object.

magnars07:05:07

You can't do (fn [& args] ,,,) ?

p-himik07:05:37

If you need specifically arguments, then it's (js-arguments).

👍 4
byrongibby07:05:01

No, args would be an array and the receiving code expects an object

Benjamin11:05:58

https://github.com/arttuka/reagent-material-ui/blob/4fc4b44891919d2b84160eb411d52227dd89e0a5/src/core/reagent_mui/material/textarea_autosize.cljs#L26 Hi, do you know enough react to say why this line throws An effect function must not return anything besides a function

Benjamin11:05:56

development.js:68 Warning: An effect function must not return anything besides a function, which is used for clean-up. You returned null. If your effect does not require clean up, return undefined (or nothing).
at reagent_mui$material$textarea_autosize$textarea_autosize
TypeError: destroy is not a function
    at commitWork (react-dom.development.js:20553)
happens when I add add and remove a style to a parent:
width: 0;
  overflow: none;

p-himik11:05:30

What is the full stacktrace?

Benjamin12:05:34

> 4pdf.js:1836 Warning: _bindResetFormAction - "resetForm" action not supported, ensure that the fieldObjects parameter is provided. > 2react-dom.development.js:68 Warning: An effect function must not return anything besides a function, which is used for clean-up. You returned null. If your effect does not require clean up, return undefined (or nothing). > at reagent_mui$material$textarea_autosize$textarea_autosize (http://localhost:3000/designer-js/cljs-runtime/reagent_mui.material.textarea_autosize.js:41:42) > at MuiOutlinedInput-input (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at div > at MuiOutlinedInput-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$InputBase$InputBase.js:16:521) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$OutlinedInput$OutlinedInput.js:12:196) > at div > at MuiFormControl-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$FormControl$FormControl.js:7:344) > at MuiTextField-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$TextField$TextField.js:7:169) > at reagent_mui.material.text_field.text_field (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at MuiFormControl-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$FormControl$FormControl.js:7:344) > at nc-error-boundary (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at nc_platform.common_frontend.components.error_boundary.error_boundary (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at nc_platform.common_frontend.components.form.form_group.form_group (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at property-input-field (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at editor-field (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at div > at nc_platform.designer.designer.property_editor.core.property_group (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at MuiAccordionDetails-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$AccordionDetails$AccordionDetails.js:5:241) > at div > at div > at MuiCollapse-wrapperInner (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at div > at MuiCollapse-wrapper (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at div > at MuiCollapse-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at Transition (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$react_transition_group$cjs$Transition.js:3:310) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$Collapse$Collapse.js:9:154) > at div > at MuiPaper-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$Paper$Paper.js:8:139) > at MuiAccordion-root (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$emotion$react$dist$emotion_element_b63ca7c6_cjs_dev.js:4:7) > at eval (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$material$Accordion$Accordion.js:10:293) > at nc_platform.common_frontend.components.accordion.accordion (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at nc_platform.designer.designer.property_editor.core.property_form_builder (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at nc_platform.designer.designer.property_editor.core.application_property_editor (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at nc_platform.designer.designer.property_editor.core.property_editor_pane (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at nc_platform.designer.designer.side_tabs.tab_panel (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at nc_platform.designer.designer.side_tabs.side_tab_content (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at div > at nc_platform.designer.designer.settings_column.settings_column (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at div > at div > at nc_platform.designer.designer.views.designer_page (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at div > at div > at nc_platform.common_frontend.components.loading.with_loader (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at StyledEngineProvider (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$styled_engine$node$StyledEngineProvider$StyledEngineProvider.js:1:480) > at InnerThemeProvider (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$system$ThemeProvider$ThemeProvider.js:1:478) > at ThemeProvider (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$private_theming$node$ThemeProvider$ThemeProvider.js:1:461) > at ThemeProvider (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$system$ThemeProvider$ThemeProvider.js:2:113) > at reagent_mui.styles.theme_provider (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at LocalizationProvider (http://localhost:3000/designer-js/cljs-runtime/module$node_modules$$mui$x_date_pickers$node$LocalizationProvider$LocalizationProvider.js:1:509) > at nc_platform.common_frontend.base_provider.base_provider (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > at nc_platform.designer.views.layout (http://localhost:3000/designer-js/cljs-runtime/reagent.impl.component.js:499:43) > printWarning @ react-dom.development.js:68 > error$jscomp$0 @ react-dom.development.js:44 > commitLifeCycles @ react-dom.development.js:20590 > commitLayoutEffects @ react-dom.development.js:23427 > callCallback @ react-dom.development.js:3946 > invokeGuardedCallbackImpl @ react-dom.development.js:3995 > invokeGuardedCallback @ react-dom.development.js:4057 > commitRootImpl @ react-dom.development.js:23152 > exports.unstable_runWithPriority @ scheduler.development.js:469 > runWithPriority$1 @ react-dom.development.js:11277 > commitRoot @ react-dom.development.js:22991 > performSyncWorkOnRoot @ react-dom.development.js:22330 > eval @ react-dom.development.js:11328 > exports.unstable_runWithPriority @ scheduler.development.js:469 > runWithPriority$1 @ react-dom.development.js:11277 > flushSyncCallbackQueueImpl @ react-dom.development.js:11323 > flushSyncCallbackQueue @ react-dom.development.js:11310 > scheduleUpdateOnFiber @ react-dom.development.js:21894 > enqueueForceUpdate @ react-dom.development.js:12505 > Component.forceUpdate @ react.development.js:385 > re_frisk$reagent$impl$batching$run_queue @ batching.cljs:37 > eval @ batching.cljs:88 > eval @ batching.cljs:98 > eval @ batching.cljs:78 > G__58381 @ batching.cljs:59 > G__64129 @ batching.cljs:20 > requestAnimationFrame (async) > re_frisk$reagent$impl$batching$next_tick @ batching.cljs:16 > eval @ batching.cljs:59 > reagent$impl$batching$schedule @ batching.cljs:125 > reagent$ratom$rea_enqueue @ ratom.cljs:120 > eval @ ratom.cljs:399 > reagent$ratom$handle_reaction_change @ ratom.cljs:345 > reagent$ratom$notify_w @ ratom.cljs:104 > eval @ ratom.cljs:146 > cljs$core$resetBANG_ @ core.cljs:866 > cljs$core$reset_BANG_ @ core.cljs:4527 > eval @ fx.cljc:185 > re_frame$fx$do_fx_after @ fx.cljc:56 > re_frame$interceptor$invoke_interceptor_fn @ interceptor.cljc:70 > re_frame$interceptor$invoke_interceptors @ interceptor.cljc:108 > re_frame$interceptor$execute @ interceptor.cljc:201 > re_frame$events$handle @ events.cljc:65 > eval @ router.cljc:179 > eval @ router.cljc:198 > eval @ router.cljc:146 > eval @ router.cljc:169 > G__59588 @ router.cljc:187 > channel.port1.onmessage @ nexttick.js:195 > 2react-dom.development.js:3946 Uncaught TypeError: Cannot read property 'apply' of null > at HTMLUnknownElement.callCallback (react-dom.development.js:3946) > at Object.invokeGuardedCallbackImpl (react-dom.development.js:3995) > at invokeGuardedCallback (react-dom.development.js:4057) > at commitUnmount (react-dom.development.js:20451) > at unmountHostComponents (react-dom.development.js:21005) > at commitMutationEffects (react-dom.development.js:21348) > at HTMLUnknownElement.callCallback (react-dom.development.js:3946) > at Object.invokeGuardedCallbackImpl (react-dom.development.js:3995) > at invokeGuardedCallback (react-dom.development.js:4057) > at commitRootImpl (react-dom.development.js:23122)

p-himik12:05:14

No clue right away - I'd try to debug that. But it seems weird that your stacktrace includes re-frisk.

Benjamin12:05:32

what is your strategy to debug such a thing? Minimal repro?

p-himik12:05:10

Personally, in similar cases I break on the line where an error/warning is issued and study the callstack, its data, and try to understand where the relevant data came from. In 90% of the cases, that's enough. In the remaining 10%, an MRE would definitely help. If that doesn't bear fruit, try to reduce it even further (e.g. by using MUI directly and not via that wrapper).

Stuart15:05:34

Hi, I'm trying to use a reagent atom to have some local state that I just want to toggle between true / false.

(defn app []
  (let [is-expanded (r/atom false)] << r/atom comes from reagent.core
   [:div 
    [,,, stuff ,,
       [:a.nav-link
          {:on-click #(swap! is-expanded not)}  << trying to swap the atom in this <a> tag click.
         ,,, stuff ,,,
    ] ))
I've tried debugging it using prn statements
{:on-click #(do (prn "before" @is-expanded)
                (swap! is-expanded not)
                (prn "after" @is-expanded))}
This always prints
before false
after true
Then on next click, it will again print
before false
after true
If I change it from a bool to an int and pass inc, then I get the expected 1 2 3 4 5 ... etc What am I misunderstanding here ?

p-himik15:05:29

For future reference, #C0620C0C8 is a better place for such questions. I have read only the first three lines of your code and I'm certain that all you need to do is to use a form-2 component or r/with-let.

Stuart15:05:26

thanks! Yep, using a form2 component work. It now toggles fine!

Stuart15:05:47

What is the difference then between the bool and the int, where the int worked without the form2 ?

p-himik15:05:06

No clue, especially given that I don't have all of the relevant code. But I wouldn't think about it too hard. Creating ratoms in form-1 components without r/with-let makes little sense, so it doesn't really matter why things worked the way they did.

👍 2
kanwei18:05:36

I'm trying to take an HTML string in CLJS and adding an "aria-label" attribute to each link. Here's my code:

(defn link->screenreader-accessible [html-str]
  (let [parser (js/DOMParser.)
        serializer (js/XMLSerializer.)
        doc (.parseFromString parser html-str "text/html")
        anchor-links (.querySelectorAll doc "a")]
    (doseq [link anchor-links]
      (let [text (.-textContent link)]
        (set! (.-aria-label link) text)))
    (.serializeToString serializer doc)))
However, I get this warning and it also doesn't work:
89 |         (set! (.-aria-label link) text)))
---------------------^----------------------------------------------------------
 Cannot infer target type in expression (. link -aria-label)
--------------------------------------------------------------------------------

thheller18:05:52

dom attributes generally are camel cased when setting through code

thheller18:05:23

if you want it a bit more straightforward try (.setAttribute link "aria-label" text)

thheller18:05:07

or (set! (.-ariaLabel link) text)

kanwei18:05:43

it worked! thanks!!

Jack Gee19:05:46

Hey! I'm attempting to use the .fetch api in clojurescript to return some data from an open api. When I get the promise object, how do I get it's values into a clojure/cljs map? I have tried various functions on this but no luck:

[quote-data (-> (.fetch js/window "")
                       (.then #(.json %)))]

p-himik19:05:11

You have to store the data somewhere in the .then handler. Or pass the promise somewhere else and access the data via yet another .then without any intermediate storage.

john22:05:16

Yeah, just add one more (.then #(do-stuff-with-json-now %)) to your thread

skylize00:05:19

(Except for usually-not-recommended "sync" versions of some APIs in NodeJS,) I/O in JavaScript is always async. You can only get access to the async results through callbacks. Promises are are mostly-monadic wrapper around this callback system, giving you a thing that can be passed around synchronously. But you still cannot synchronously access the value inside that Promise. You need to pass a callback into the Promise context (via .then) which can be called asynchronously on your behalf when/if that value actually exists. The correct suggestions above are based on the fact that .then returns another Promise. So you can chain .then calls together and/or pass around a Promise that already has a .then attached.

john00:05:21

Yeah, promises are sticky like macros - once you're in one, you can never escape

john00:05:48

Better than callback hell, but still in the same stickiness bucket

john00:05:40

Unless you're running in a webworker, of course. Then you can convert async to sync results, if you're willing to wait for the serialization/wire calls

john22:06:21

Yeah, cljs-thread will let you turn a blue function red, with a cost

john22:06:23

To mitigate that cost, I'm working on a shabby spike of persistent data structures on SABs with builtin garbage collection, for synchronous access to data across worker boundaries

john22:06:44

It's not fully working yet though

john23:06:07

One thing I haven't tried yet: just let the persistent nodes and leaves be individual SABs and just pass them in their trie structure as a transferrable object :thinking_face: Not sure how the memory management would play out. Might have to track nodes with weakmaps

john23:06:36

Like other threads don't need to see your derivatives of the data structures they passed you, unless you pass it back... Unless they both have access to the same data in an atom or similar primitive, in which case you need a memory pool, allocation, garbage collection, etc

john23:06:22

All inside a shared memory pool SAB, which is what I've been hacking on. I'll look into this idea of hybrid persistent SAB backing

p-himik23:06:15

I feel like this thread got drastically off-topic at the span of a single screen. :)

john23:06:20

Yeah I'm totally rambling. I guess the moral of the story is that we could have efficient transition between two color/ one color semantics in cljs one day

Arthur Fücher23:05:17

Hello! When iterating in a list to create components... any opinions about using map or for ? In react I used to use map , but I saw a lot of code in ClojureScript using for

Sturm00:05:19

I'm assuming you're creating hiccup forms? These two examples would be equivalent:

(def names ["Rupert" "Regina"])

;; for
(for [name names]
  ^{:key name} [:li name])

;; map
(map
  (fn [name] ^{:key name} [:li name])
  names)
The for example is a touch shorter and perhaps more like a typical templating language.

👍 4
Ben Lieberman00:05:55

Also for gives you access to the :let , :when , and :while bindings that are really useful and give you much more control than just plain map

😇 2
2
thheller05:05:34

for in JS is also entirely different to for in CLJS, so in JS you cannot really use for in this context

delaguardo08:05:40

Semantically speaking, map and for in clojure are very different: map is a function and for is a declarative list comprehension expression. For example: map can be used as a transducer and for can not.

Arthur Fücher14:05:45

Nice, thanks for your answers!! • So, if I have a simpler case where I have a fn that receives the data and return the component, there is no concern to use map, right? (map my-comp data) But for more complex cases where I need to add more logic inside the loop, for is an option. • what means ^{:key name} ? it add the key where? since in the example it is outside from the :li component. Sorry, noob question here

delaguardo14:05:57

^{,,,} before object ads metadata to that object. check reagent documentation about details, specifically how to render a list of items

Arthur Fücher14:05:39

ohh nice, searched in cljs docs but did not found... thanks for pointing that is from reagent thanks2

isak16:05:28

Another reason I like for, in addition to what Ben mentioned: The collection comes first, and the code is easier to read, especially if the body of the fn that would be passed to map is long. One point in favor of map - it is easier to switch to other variations, like map-indexed, keep, etc. And you can use ->> if you want to have the collection first in the code.