Fork me on GitHub
#reagent
<
2018-08-17
>
urbanslug14:08:57

Hey, guys using soda ash. How do you guys do theming? e.g if I want to use their components but with a dark theme. I don't get what the semantic ui docs are trying to explain

polymeris14:08:10

I haven't used soda-ash, but am considering it, and for theming I was thinking of adding a LESS compilation task to my leiningen project?

polymeris14:08:02

Then import the semantic stuff into my root LESS file

urbanslug14:08:05

the components are taking an {:invtert true}

luposlip14:08:48

Guys! I've spent all day trying to figure out an idiomatic way of using a react component like this in a reagent app: https://whoisandy.github.io/react-rangeslider/ I've fetched the library (and @cljs-oss/module-deps) via npm, refer to them via project.clj foreign-libs:

clojure
{:file "resources/public/js/rangeslider.min.js"
                  :provides ["react-rangeslider"]
                  :module-type :es6}
And import it in my view.cljs via ns require [react-rangeslider :as range-slider] I can't find the idiomatic way of making it work - should I use form-3?

urbanslug14:08:49

I think I'll use inverted for now

urbanslug14:08:12

You want to use react components in reagent that's the issue?

urbanslug14:08:38

or how to import them in the namespace?

luposlip14:08:01

Yes @urbanslug, it seems hackable, but still way too tedious, and seems like some react components have to be wrapped before they can be used (as seems to be the case with the react-rangeslider)

luposlip14:08:24

The import works fine, but I can't use it directly in the hiccup.

urbanslug14:08:03

which build tool? lein?

luposlip14:08:00

I believe I've come close with this: (r/adapt-react-class (. range-slider -default))

luposlip14:08:15

But when I use it in hiccup like [(r/adapt-react-class (. range-slider -default))]I keep getting errors such as .default is not a constructor, or something telling me I've passed an object instead of a component.

urbanslug14:08:21

You can do something like

[:> nameOfDefaultExport ...]

luposlip14:08:06

Problem I think is that the react component react-rangeslider needs to be wrapped/prototyped, as in their examples on the website: https://whoisandy.github.io/react-rangeslider/. I don't know the idiomatic way of doing that in a reagent setup.

urbanslug14:08:46

(:require ["react-rangeslider" :default Slider])

[:div#my-slider
  [:> Slider {:value 122}]]

luposlip14:08:52

If I try this: [:> Slider #{}], I get this:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

urbanslug14:08:56

but that import might be shadow only

urbanslug14:08:22

not #{} but {}

urbanslug14:08:39

idk how to use react slider so I'm not sure what it takes

luposlip14:08:17

Sure, just a map. Same error.

luposlip14:08:05

One of their examples is as follows:

import React, { Component } from 'react'
import Slider from 'react-rangeslider'

class Horizontal extends Component {
  constructor (props, context) {
    super(props, context)
    this.state = {
      value: 10
    }
  }

  handleChangeStart = () => {
    console.log('Change event started')
  };

  handleChange = value => {
    this.setState({
      value: value
    })
  };

  handleChangeComplete = () => {
    console.log('Change event completed')
  };

  render () {
    const { value } = this.state
    return (
      <div className='slider'>
        <Slider
          min={0}
          max={100}
          value={value}
          onChangeStart={this.handleChangeStart}
          onChange={this.handleChange}
          onChangeComplete={this.handleChangeComplete}
        />
        <div className='value'>{value}</div>
      </div>
    )
  }
}

export default Horizontal

urbanslug14:08:16

(r/render [my-slider-fn] (.getElementById js/document "divTag"))

luposlip14:08:13

And my-slider-fn would then be like what?

urbanslug14:08:58

(:require ["react-rangeslider" :default Slider]
          [reagent.core :as r])

(defn my-slider-fn []
  [:div#my-slider
   [:> Slider {:value 122}]])



(r/create-class {:reagent-render      [:div#parent]
                 :component-did-mount (r/render [my-slider-rn]
                                                (.getElementById js/document "slider-parent"))})

urbanslug14:08:50

(defn init
  []
  (r/create-class {:reagent-render      [:div#parent]
                   :component-did-mount (r/render [my-slider-rn]
                                                  (.getElementById js/document "slider-parent"))}))

luposlip14:08:11

Will try that out @urbanslug! Reverting in a bit.

luposlip14:08:34

Get this error:

Only :as, :refer and :rename options supported in :require / :require-macros; offending spec: ["react-rangeslider" :default Slider]

luposlip14:08:33

If I replace the ns require with [react-rangeslider :as range-slider :refer [Slider]] and then use your my-slider-fn, I get this error:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

luposlip14:08:04

Probably because the build cannot find Slider

luposlip14:08:39

Next option: I just have this in the ns require: [react-rangeslider :as range-slider] Then the my-slider-fn is like this:

(defn my-slider-fn []
  [:div#my-slider
   [:> (. range-slider -default) {:value 122}]])

luposlip14:08:39

The result of that is:

Uncaught TypeError: _resizeObserverPolyfill2$$module$home$luposlip$folder$project$node_modules$react_rangeslider$lib$Rangeslider.default is not a constructor
    at Slider.componentDidMount (Rangeslider.js:29)

luposlip14:08:28

react-dom.inc.js mentions that

The above error occurred in the <Slider> component:
    in Slider
    in div
    in project.views.my_slider_fn

luposlip14:08:24

I'll give it a 30 minutes break - thanks for your input so far @urbanslug! When I get this to work I'll definitely write a blog post about it, have been browsing through lots of posts, forums, changelogs (reagent and re-frame) and the new stuff in cljs 1.9.x on npm imports, commonjs compatibility etc. But so far hasn't seen the light 😉

urbanslug14:08:43

sorry my import is shadow-cljs method

urbanslug14:08:54

you should import react-slider your own way

urbanslug14:08:31

which you figured out

urbanslug14:08:12

why are you doing this (. range-slider -default) ?

urbanslug14:08:45

hmm I assume that's how to refer to default exports when using lein

luposlip14:08:28

It's the closest I get to something that looks like a react component. But it's not usable as you can see from the above.

luposlip14:08:15

The default gets me a class of some sort.

urbanslug14:08:25

in the error "Rangeslider.default is not a constructor"

urbanslug14:08:38

it seems you should be leaving out the default

urbanslug14:08:46

because the export is RangeSlider

urbanslug14:08:25

Look at Rangeslider.default is not a constructor

urbanslug14:08:55

is that really how to call the default export?

luposlip14:08:22

Yeah, then the complaint is that it's just an object

luposlip14:08:11

Not a function

urbanslug14:08:05

I don't use lein so I'm not sure how to call es6 default exports in your case

luposlip14:08:37

Is it easy to test shadow instead?

luposlip15:08:29

Or my question could have been : the example you provided, does it actually work on your setup?

dogenpunk15:08:30

Hello, I have some code like this:

(defn header-title
  [title & dt]
  [:h1 title
   [:small (format-header-date dt)]])
(defn agenda-header
 []
[:div
  (header-title "Today" (js/Date.)])
When this renders I get “NAN” in the <small> tag. When I step through in the debugger, the argument that gets passed to format-header-date is reported as a cljs.core.IndexedSeq rather than a JS Date. Anyone have an idea why?

dogenpunk15:08:45

Calling the format-header-date function in the REPL returns the expected formatted string

luposlip15:08:38

How's the input dt generated?

luposlip15:08:39

Why is it optional?

justinlee15:08:42

@urbanslug the problem is almost certainly in how you’re importing the component. you do not need to do all those shenanigans to get it to render once you figure out how to import it. you will just need to do a [:> ReactRangeSlider {options}]

urbanslug15:08:45

well it's really not my code 😛

justinlee16:08:06

if there is a UMD build or some kind of es5 build, then it should attach the component to a global, which will avoid you having to mess with the es6 default import

urbanslug16:08:11

He's using lein

urbanslug16:08:39

I think the problem is how to use a default import with lein

urbanslug16:08:06

He got

Only :as, :refer and :rename options supported in :require / :require-macros; offending spec: ["react-rangeslider" :default Slider]

urbanslug16:08:17

when he used the shadow-cljs way

lilactown16:08:30

@luposlip one trick when I’m having trouble with importing npm libs is just to console.log what is being imported

justinlee16:08:45

oh sorry it was luposlip not you

lilactown16:08:36

(ns foo
  (:require ["react-rangeslider" :as range-slider]))

(js/console.log range-slider)

justinlee16:08:25

right so @luposlip if you just use the prebuilt & minified version, you can access the component using js/ReactRangeslider. https://github.com/whoisandy/react-rangeslider#getting-started That’s a lot easier than messing with es6 imports

urbanslug16:08:26

@lee.justin.m you taught me well 😄

justinlee16:08:45

from here you can just [:> js/ReactRangeslider {:value 15 ...}]

luposlip16:08:51

Thanks @lee.justin.m, will test that later :)