Fork me on GitHub
#clojurescript
<
2023-05-29
>
郭育賢09:05:02

Hello! I'm writing a re-frame app and trying to use a JS datepicker component inside it, but I've been really struggling to make it work. The source is here: https://github.com/goderich/hr I would like to change the html date inputs for this: https://github.com/Hacker0x01/react-datepicker/ (or flatpickr, either one is fine). I'm vaguely aware that I would need to use form-3 components (as seen [here](https://github.com/day8/re-frame/blob/master/docs/Using-Stateful-JS-Components.md) and [here](https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md)). However, I can't even get the DatePicker component to show up in the browser!

p-himik09:05:19

For future reference - #C0620C0C8 would be a better channel for this. There's also #C073DKH9P but it uses Reagent for rendering and that's exactly what you're having problems with. But what exactly have you tried so far? What is the code that attempts to render that component?

郭育賢09:05:26

I'm calling the react-datepicker lib in views.cljs as follows (this part is not on GitHub cause it don't work): ["react-datepicker" :as react-datepicker :refer [DatePicker]] I then try to create a function for it like this:

(defn datepicker-inner []
  (let [date (js/Date.)]
    (reagent/create-class
     {:display-name "date picker"

      :component-did-mount
      (fn [comp]
        (println "date picker did mount"))

      :reagent-render
      (fn []
        [:div
         [DatePicker
          {:selected date
           :onChange (fn [] (println "changed!"))}]])
      })))
But the browser is complaining that "DatePicker" is not a function.

郭育賢09:05:00

My bad, I wasn't aware of #C0620C0C8

郭育賢09:05:50

I'm just trying to make the date picker show up at all. I figure once that is done, I can figure out the rest from there.

p-himik09:05:26

Two things to do: 1. Log the value of DatePicker and confirm that it looks like a React component to exclude any possibility of an improper import 2. Instead of [DatePicker ...] use [:> DatePicker ...] - it's required to let React components work with Reagent hiccup.

郭育賢09:05:32

I should also say that I have zero JS knowledge...

郭育賢09:05:04

Thanks p-himik! I've tried 2 already, and it didn't work at all.

p-himik09:05:06

By "log the value" I mean use (js/console.log ...) since it will show the object's internals in the JS console of your browser. Regular printing won't do here.

p-himik09:05:27

If (2) didn't work then most likely the import is improper and you'll see it in (1).

郭育賢09:05:42

I'm seeing this error: Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined.

郭育賢09:05:38

Hmmm. How should I fix the import? I'm at a bit of a loss here, sorry. Does the lib need to be in shadow-cljs.edn?

郭育賢09:05:16

I pulled it in with npm install

p-himik09:05:50

Log the value of react-datepicker and send a screenshot of the result with the top level expanded.

p-himik09:05:07

You installed it correctly, it's just that :require that's wrong.

p-himik09:05:10

(Most likely)

郭育賢09:05:59

Apologies for the stupid question, but what exactly do you mean by logging the value of react-datepicker?

郭育賢09:05:20

How and where should I log it?

p-himik09:05:05

Right after the (ns ...) form, add (js/console.log 'xxx react-datepicker). Then open the browser's DevTools, navigate to Console, and load the web page in the main window. In the console, you should see a record that starts with xxx and is followed by some value. That value should be an expandable object - expand the top level, make a screenshot, and attach it here.

郭育賢09:05:32

Cheers! On it

郭育賢09:05:11

I think CalendarContainer is from that library, and it's showing up in the logs.

p-himik09:05:16

First of all, that xxx is displayed as an object in your console and not as a CLJS symbol. That means that you should install https://github.com/binaryage/cljs-devtools/ - it will make all CLJS value that are logged to the console be properly displayed. The second object has a default key - most likely it's a so-called default export from the react-datepicker library. And I'm gonna go out on a limb and guess that that's DatePicker itself. So what you wanna do then is require the library as ["react-datepicker$default" :as DatePicker]. This section of the docs describes all the important bits of how one might require NPM packages: https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages

郭育賢09:05:52

Thank you! I'll try that now.

郭育賢09:05:46

It appeared!

郭育賢09:05:10

Thank you so much for your time and insight, @U2FRKM4TW!

👍 2
郭育賢09:05:21

I've been banging my head against the wall for days on this...

郭育賢09:05:38

While I have you here, one more quick question

p-himik09:05:13

> banging my head against the wall for days Heh, yeah, don't do that unless you always have some lead to pursue. When you're fully stuck for more than 20-30 minutes, just ask someone.

👍 2
郭育賢09:05:50

The library assumes that the users will import the css directly in their JS source: https://github.com/Hacker0x01/react-datepicker/ We can't do that in CLJS can we? From what I understand, the only way is to import it in index.html

郭育賢09:05:21

> When you're fully stuck for more than 20-30 minutes, just ask someone. Yeah I should be more open to asking for help. Self-reliance is great, but sometimes it bites you in the ass. This was one of those times XD My complete ignorance of JS, React, and Reagent isn't helping.

p-himik09:05:49

> We can't do that in CLJS can we? We can't indeed. Including it directly in HTML is one option, but you'll have to make that file available to your web server. I'd probably just copy it into your resources folder with a build hook and then add it to .gitignore. I myself use SASS, so I simply require all such files in my main .scss and then it gets built and loaded in the main HTML.

p-himik09:05:19

Or rather, we can, but that would require using webpack and organizing your whole app around that.

郭育賢09:05:45

This is a frontend-only app. I'm not using a server, just hosting it on GH pages 🙂

郭育賢09:05:59

Just a simple tool for the wife to use at work

p-himik09:05:49

Well, there is a server still - it's just on GitHub's premises. And the statement still stands true - you gotta make that CSS file available to the server somehow, which is probably just putting it into the right dir.

郭育賢09:05:26

Yeah, I'll try to figure that out next. Thanks again @U2FRKM4TW!

👍 2
p-himik09:05:35

BTW if it's just a small app then you might find https://github.com/day8/re-com/ sufficient. Then you won't have to deal with NPM packages, at least not directly. And the library does have a date picker component.

🙌 1
郭育賢10:05:28

Ah, yes, I've seen that while searching for libs. Sadly, it doesn't seem to do date ranges, which is what I need 😕

p-himik10:05:08

A date range is just two dates. ;)

郭育賢10:05:20

Very true 🙂

郭育賢10:05:01

I'll try to figure out the CSS for this at least, if only as an exercise in using JS from CLJS.