clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
valerauko 2021-03-29T02:01:36.318700Z

What's the CLJS equivalent of a JS for await (const item of channel)?

raspasov 2021-03-29T08:24:16.320400Z

Take a look at https://clojurescript.org/guides/promise-interop

raspasov 2021-03-29T08:24:52.320600Z

There’s no “await” in ClojureScript; some discussion here: https://groups.google.com/g/clojurescript/c/scUMhU-ctEM

valerauko 2021-03-29T09:33:48.321200Z

Yeah this was much more pain than it should be.

thheller 2021-03-29T10:36:30.322100Z

deno has a (http/listenAndServe options (fn [req] ...)) which makes for a much easier API from CLJS than using the await asynciterator stuff

💯 1
valerauko 2021-03-29T10:45:27.322300Z

yay time to use that instead!

valerauko 2021-03-29T10:51:40.322500Z

thanks!

tvirolai 2021-03-29T06:23:42.319700Z

I'm having trouble compiling a ClojureScript project to a React component to be used in JavaScript. The problem seems to be related with Material UI, which the project is using. When I'm trying to render the exported component on the JavaScript side, I'm getting an error, the full stack trace is in the thread. This is the kind of export I'm trying to do. Here, export1 works and export2 produces the error, as it contains a component from Material UI.

(ns testinki.core
  (:require [reagent.core :as r]
            [reagent.dom :as d]
            [reagent-material-ui.core.chip :refer [chip]]))

(defn export1 []
  (r/create-element (r/reactify-component (fn []
                                            [:div [:h2 "Hi guys"]])) #js{}))
(defn export2 []
  (r/create-element (r/reactify-component (fn []
                                            [:div [:h2 "Hi there"]
                                             [chip {:label "Hello again"}]])) #js{}))
The problem seems to be related the use of React Hooks inside Material UI, right? Is there a workaround for exporting components using Material UI? I tried googling the issue but can't seem to figure it out.

p-himik 2021-03-29T08:12:15.320200Z

If it works in the dev setup, then it should work in production as well. Really strange to see that error. You can try replacing (r/create-element (r/reactify-component ...)) with just (r/as-element ...). And if the code above doesn't work in dev as well, then Reagent documentation contains information how to create functional components that can work with hooks.

tvirolai 2021-03-29T09:21:44.320800Z

Thanks, unfortunately that doesn't seem to help. To be clear, the application does work in the local development environment and I can get my it to work even in JavaScript side by exporting it as an ESM module (using Shadow-CLJS) that contains all the dependencies and mounts itself to a div id. However, when trying to get it to work as a React component like in the snippet below, I'm running to the error mentioned.

import { Component1 } from './testproject'

function App() {
  return (
    <div className="App">
        <Component1 />
    </div>
  );
}

export default App;

alpox 2021-03-29T10:09:44.321900Z

Im not sure what the error could come from exactly but I would have expected that r/create-element shouldnt be used as react (JSX) expects a comonent and not an already created element

tvirolai 2021-03-29T11:00:24.322700Z

The strange thing is, the setup for exporting a piece of Reagent as a React component works just fine if the code does not include Material UI components. So the crux of the matter seems to be the way Material UI uses React Hooks, which cannot be used in class components - which this setup produces...

p-himik 2021-03-29T11:32:49.323100Z

IIRC the hooks cannot be used in a class component directly. So a class component is still able to use a function component that uses hooks. Maybe the advanced compilation somehow removes some thing function component layer and inlines it within the class component. But that seems like magic to me. Have you tried forcing Reagent to produce a function component from that particular [:div ...]?

tvirolai 2021-03-29T06:37:39.319900Z

Uncaught Error: Minified React error #321; visit <https://reactjs.org/docs/error-decoder.html?invariant=321> for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
    at z (testproject.js:14)
    at Object.d.useContext (testproject.js:20)
    at b.default (testproject.js:408)
    at testproject.js:421
    at testproject.js:437
    at renderWithHooks (react-dom.development.js:14985)
    at updateForwardRef (react-dom.development.js:17044)
    at beginWork (react-dom.development.js:19098)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at beginWork$1 (react-dom.development.js:23964)
    at performUnitOfWork (react-dom.development.js:22776)
    at workLoopSync (react-dom.development.js:22707)
    at renderRootSync (react-dom.development.js:22670)
    at performSyncWorkOnRoot (react-dom.development.js:22293)
    at scheduleUpdateOnFiber (react-dom.development.js:21881)
    at updateContainer (react-dom.development.js:25482)
    at react-dom.development.js:26021
    at unbatchedUpdates (react-dom.development.js:22431)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:26020)
    at Object.render (react-dom.development.js:26103)
    at Module.&lt;anonymous&gt; (index.js:7)
    at Module../src/index.js (index.js:18)
    at __webpack_require__ (bootstrap:856)
    at fn (bootstrap:150)
    at Object.1 (reportWebVitals.js:14)
    at __webpack_require__ (bootstrap:856)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1
z @ testproject.js:14
d.useContext @ testproject.js:20
b.default @ testproject.js:408
(anonymous) @ testproject.js:421
(anonymous) @ testproject.js:437
renderWithHooks @ react-dom.development.js:14985
updateForwardRef @ react-dom.development.js:17044
beginWork @ react-dom.development.js:19098
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22776
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
scheduleUpdateOnFiber @ react-dom.development.js:21881
updateContainer @ react-dom.development.js:25482
(anonymous) @ react-dom.development.js:26021
unbatchedUpdates @ react-dom.development.js:22431
legacyRenderSubtreeIntoContainer @ react-dom.development.js:26020
render @ react-dom.development.js:26103
(anonymous) @ index.js:7
./src/index.js @ index.js:18
__webpack_require__ @ bootstrap:856
fn @ bootstrap:150
1 @ reportWebVitals.js:14
__webpack_require__ @ bootstrap:856
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
index.js:1 The above error occurred in the &lt;ForwardRef&gt; component:

    at <http://localhost:3000/static/js/main.chunk.js:11931:19>
    at div
    at c (<http://localhost:3000/static/js/main.chunk.js:41823:18>)
    at ex_testproject_Component2
    at div
    at App

Consider adding an error boundary to your tree to customize error handling behavior.
Visit <https://reactjs.org/link/error-boundaries> to learn more about error boundaries.

simongray 2021-03-29T14:09:28.325400Z

I would like to make a reagent wrapper library for a bunch of 10-year old JS code. The JS code itself bundles like 20 twenty different JS files that it needs. Is there some way to include this all of this JS code with the compiled ClojureScript bundle?

simongray 2021-03-29T14:10:17.326200Z

I have lots of CLJS experience, minimal JS experience, and no experience trying to wrap JS code.

simongray 2021-03-29T14:23:13.326600Z

There is https://clojurescript.org/reference/packaging-foreign-deps but is that still the way to go?

simongray 2021-03-29T14:24:38.326900Z

Apparently there is an issue for the lack of documentation: https://github.com/clojure/clojurescript-site/issues/224

simongray 2021-03-29T14:34:34.327500Z

Also found this decade old resource: http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html

thheller 2021-03-29T14:40:52.327800Z

@simongray how is the JS bundled and used now?

thheller 2021-03-29T14:44:46.329100Z

and why do you intend to bundle it together with the CLJS code? why not just keep it as a separate script?

simongray 2021-03-29T14:46:13.329500Z

How would I distribute it as a library then?

simongray 2021-03-29T14:47:26.330600Z

And honestly, I would prefer more explicit dependencies than this automagic script

thheller 2021-03-29T14:47:29.330800Z

well from glancing at this code I can tell you that this is not going to be fun. the code is clearly not written in a bundler friendly style so you are going to have to make adjustments no matter what

simongray 2021-03-29T14:47:36.331Z

right

simongray 2021-03-29T14:49:42.333400Z

My plan was to make som adjustments either way, remove as much as possible and bundle the remainder together with some CLJS to make a reagent component

thheller 2021-03-29T14:49:47.333600Z

so this code is really designed to be included as a separate script tag. the bundler cannot change that really your only option is rewriting the code

simongray 2021-03-29T14:50:23.334100Z

hm…

simongray 2021-03-29T14:50:43.334700Z

so the bundler you’re talking about is ClojureScripts built-in way to handle foreign libs?

simongray 2021-03-29T14:51:32.335500Z

The files that end up being included look like this

thheller 2021-03-29T14:52:30.336900Z

bundler as in generic term for bundler. be that CLJS, shadow-cljs, webpack or really anything bunlding JS

thheller 2021-03-29T14:52:52.337500Z

:foreign-libs will not help you here (especially since shadow-cljs doesn't support them)

simongray 2021-03-29T14:52:57.337700Z

hmmm

simongray 2021-03-29T14:53:12.338Z

I really just need a way to load a bunch of JS code in advance

simongray 2021-03-29T14:53:58.339400Z

whatever is the shortest path there, I’ll take ity

thheller 2021-03-29T14:54:13.339800Z

I can give you shadow-cljs specific options but those will not work with regular CLJS

simongray 2021-03-29T14:55:17.341Z

I was really just trying to see if there was a way to make a CLJS lib that includes some JS. I guess that is not the case?

simongray 2021-03-29T14:55:46.341800Z

if it’s just for my own project, I guess I can simply include the JS file that loads everything in the index.html

simongray 2021-03-29T14:56:10.342400Z

and then call the JS methods from ClojureScript

thheller 2021-03-29T14:58:07.343700Z

:foreign-libs would be the way to go for regular CLJS, after adjusting the code of course.

thheller 2021-03-29T14:58:51.344200Z

looks a bit different for shadow-cljs, same idea but different code adjustments 😛

thheller 2021-03-29T15:02:12.344700Z

there is one way to make it work generally but I'm unsure the code will actually survive :advanced so that might not work 😉

simongray 2021-03-29T15:07:41.345700Z

@thheller Ok. And the regular CLJS way is not supported in shadow-cljs?

thheller 2021-03-29T15:09:54.346500Z

:foreign-libs are not no. There is also CSS involved so honestly the best option for making this a library is given the users of the library instructions of where to put the code 😛

simongray 2021-03-29T15:13:50.346900Z

hm

simongray 2021-03-29T15:13:52.347100Z

sucks

simongray 2021-03-29T15:14:23.347700Z

I guess I will not be making a library then.

simongray 2021-03-29T15:15:52.348500Z

@thheller If you don’t mind my asking, why don’t you support :foreign-libs?

simongray 2021-03-29T15:16:51.349300Z

I mean, I get that it’s possibly not the ideal way to go and that shadow-cljs might do it better, but what about ecosystem cohesion?

simongray 2021-03-29T15:17:22.349600Z

does supporting the one preclude supporting the other?

simongray 2021-03-29T15:45:01.350200Z

@thheller that does assume that the only JS code worth using in CLJS comes from a Node package.

p-himik 2021-03-29T15:47:29.350900Z

I wouldn't say so - you can use any local JS file with shadow-cljs.

p-himik 2021-03-29T15:47:50.351100Z

Namely, this: https://shadow-cljs.github.io/docs/UsersGuide.html#_requiring_js

simongray 2021-03-29T16:28:57.352300Z

For your own project, but you can't use it to make a distributable library.

p-himik 2021-03-29T16:33:24.352500Z

Ah, I see, right.

thheller 2021-03-29T16:43:04.354400Z

as I said there is a way to make it work with all CLJS tools

simongray 2021-03-29T16:46:35.356Z

@thheller is there a guide somewhere?

thheller 2021-03-29T16:56:20.356100Z

very difficult to write a generic guide for this since it depends entirely on how the actual JS you are trying to include this way is written

thheller 2021-03-29T16:56:54.356300Z

in your case you'd use you'd put all the files from here

thheller 2021-03-29T16:57:02.356700Z

into a directory on your classpath. or rather the source-path of the library you are writing

thheller 2021-03-29T16:58:03.357100Z

say src/main/simongray/timeline/themes.js and so on

thheller 2021-03-29T16:58:22.357300Z

then in that file you add a goog.provide("simongray.timeline.themes") as the first line

thheller 2021-03-29T16:58:52.357500Z

with that you can include it in CLJS via (:require [simongray.timeline.themes])

thheller 2021-03-29T16:59:01.357700Z

and in this case end up using it via js/Timeline

thheller 2021-03-29T16:59:33.357900Z

you do this for every file and you are done. no extra :foreign-libs or so

thheller 2021-03-29T16:59:45.358100Z

but since CSS is involved as well this approach doesn't really work

thheller 2021-03-29T17:01:41.358300Z

I mean it works for the JS code sure but the consumer of your library would still need to do some kind of setup for the CSS

thheller 2021-03-29T17:02:04.358500Z

if they are going to do that anyways you might as well give some extra instructions on how to include the JS separately as that library intends

2021-03-29T17:16:09.362Z

We had to integrate some react components bundled as a JS UMD build into our CLJS client built with leiningen. We managed to do so by using :foreign-libs and reagent.core/adapt-react-class project.clj:

:cljsbuild {:builds {:dhp-client
                       {:source-paths ["src/cljs"]
                        :compiler {:main dhp-client.core
                                   :language-in :ecmascript6
                                   :language-out :ecmascript5
                                   :foreign-libs [{:file "resources/lib/kartklient.js"
                                                   :provides ["markerMap" "routeMap" "setCoordinateMap" "setCoordinateOnRouteMap" "setMultipleCoordinatesMap" "setMultipleCoordinatesOnRouteMap"]
                                                   :global-exports '{markerMap MarkerMap
                                                                     routeMap RouteMap
                                                                     setCoordinateMap SetCoordinateMap
                                                                     setCoordinateOnRouteMap SetCoordinateOnRouteMap
                                                                     setMultipleCoordinatesMap SetMultipleCoordinatesMap
                                                                     setMultipleCoordinatesOnRouteMap SetMultipleCoordinatesOnRouteMap}}]}}
Helper:
(ns dhp-client.helpers.kartklient
  (:require [reagent.core :refer [adapt-react-class]]
            [markerMap :as markerMap]
            [routeMap :as routeMap]
            [setCoordinateMap :as setCoordinateMap]
            [setCoordinateOnRouteMap :as setCoordinateOnRouteMap]
            [setMultipleCoordinatesMap :as setMultipleCoordinatesMap]
            [setMultipleCoordinatesOnRouteMap :as setMultipleCoordinatesOnRouteMap]))

(def marker-map (adapt-react-class markerMap))
(def route-map (adapt-react-class routeMap))
(def set-coordinate-map (adapt-react-class setCoordinateMap))
(def set-coordinate-on-route-map (adapt-react-class setCoordinateOnRouteMap))
(def set-multiple-coordinates-map (adapt-react-class setMultipleCoordinatesMap))
(def set-multiple-coordinates-on-route-map (adapt-react-class setMultipleCoordinatesOnRouteMap))
Usage:
[kk/route-map
        {:data kartdata
         :apikey api-key}]

wombawomba 2021-03-29T19:24:59.364600Z

How can I delete a __Host-prefixed cookie with CLJS? I'm able to delete it in JS using document.cookie = "__Host-Foo=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; secure'" but neither (.remove <http://goog.net|goog.net>.cookies) nor (.remove <http://goog.net|goog.net>.cookies "/" nil) nor (.clear <http://goog.net|goog.net>.cookies) seem to work.

wombawomba 2021-03-29T19:34:54.365100Z

I was finally able to expire it via (.set <http://goog.net|goog.net>.cookies "__Host-Foo" "" 0 "/" nil true) 🙂

simongray 2021-03-29T20:12:47.365300Z

ok - thank you for the rundown