Fork me on GitHub
#clojurescript
<
2023-03-04
>
Stuart11:03:20

Hi, I'm not sure if this is a reagent problem or a more general clojurescript problem, so I'm posting here. I'm trying to use the library from npm react-date-picker, but more generally I'm trying to learn how to use react npm packages from clojurescript. This is more of a learning project than anything. My first issue was I couldn't get it to load at all, and this seems to be because the react component comes bundled with css. I fixed this with thellers help (thank you again), by using webpack to build a lib.js and then shadow-cljs to build my cljs. This worked, and I now have the date picker showing on the page. Yay! Now my problem is using useState, My requires for the page looks like this:

(:require ["react" :as react]
          ["react-date-picker" :default DatePicker]
          [reagent.core :as r])
Then the code to use the DatePicker looks like this:
(let [[value onChange] (react/useState (new js/Date))]
            [:> DatePicker
             {:value value, :onChange onChange}])
However this leads to the error: > Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. If I try to run (react/useState (new js/Date)) in the repl, the output is:
:repl/exception!
; 
; [true ""]
I'm using reagent 1.2.0 I got it working doing this:
(defn date-picker []
  (let [[value onChange] (react/useState (new js/Date))]
    (r/as-element
     [:> DatePicker
      {:value value, :onChange onChange}])))

[:div
   [:> date-picker]]
Now the datepicker shows up, I can change the dates on it and it seems to work fine, what I'm stuck with now is how to do stuff in onChange that I want to do, mainly dispatch a re-frame event ? Or, more generally, have I done this all wrong ?

Stuart12:03:19

I tried: :onChange #(onChange)}] Thinking I could then add do and do my own stuff. But then when I select a date it doesn't update the selection in the picker

Stuart12:03:25

Doh! I needed :onChange #(onChange %)} Now I can do

:onChange (fn [v] (onChange v) 
                  (rf/dispatch-sync [:stuff v]))

Stuart12:03:37

Thank you for allowing me to rubber duck

p-himik12:03:51

> I got it working doing this: Not sure whether it's an optimal solution - Reagent docs on hooks suggest using a functional component.

Sam Ritchie16:03:55

I would have thought, given the hook use, you’d have to call [:f> date-picker] (note the :f>)

p-himik17:03:53

Not in this case because Stuart created a plain React component that uses Reagent Hiccup.

👍 2
Sam Ritchie17:03:24

Ah I see now

zeitstein21:03:32

Timestamp for David Nolen's appearance: https://youtu.be/8pDqJVdNa44?t=3031

❤️ 16
👍 7
2
grumplet22:03:56

I have a need to run an asynchronous clojurescript test multiple times with a changing integer parameter. This seems to be difficult to do. The nearest approach tackles the parameterisation problem. See this gist by @borkdude https://gist.github.com/borkdude/1fc2bd73c77d094fb0577c9caf9684b3, but that assumes a babashka environment. Do you think this would adapt to clojurescript somehow?

borkdude22:03:25

How I would approach that in CLJS is probably to write a function which executes the tests (`is`, etc) and then call that function multiple times in the test?

borkdude22:03:49

is your async function promise based or callback based?

borkdude22:03:20

of course you could port the above snippet/macro to CLJS as well

borkdude22:03:09

but async makes it harder indeed

grumplet22:03:01

I tried importing the gist, but got into difficulties with test-args/test-args*. Not sure these are easy to resolve. As I understand it, the cognitect test runner needs those test-vars to serialise a sequence of async tests.*

grumplet22:03:51

I think you may be right about finding an alternative approach here that avoids the standard async deftest mechanism.

borkdude22:03:00

(deftest foo
  (async done
    (-> 
    (p/doseq [x [1 2 3]]
      (p/let [x (js/fetch ""))]
      ... (is (= 200 (.-status x))))
    (p/finally done)))
The above is an example using promesa (pseudo-code)

grumplet22:03:35

Ah, I see what you are getting at there…

grumplet22:03:13

Thanks, I’ll see if it will fly….

👍 2
grumplet22:03:12

The wider context is that I am testing a calculation in a cljs app against the same calculation running in R on an OpenCPU server via an http api. I need to test the calculation works across its parameter space.

grumplet22:03:55

The async is coming from an ajax.core POST. Callback.