Fork me on GitHub
#fulcro
<
2018-12-15
>
eric.shao11:12:01

Ask a question: In a js project:

<Map zoom={3} center={this.mapCenter}>
            <Polygon path={this.state.polygonPath}>
              <PolyEditor
                active={this.state.polygonActive}
              />
            </Polygon>
          </Map>
is OK. But why in a fulcro/shadow-cljs project it will crash:
(def ui-amap (component-factory Map))
(def ui-amap-polygon (component-factory Polygon))
(def ui-amap-polyeditor (component-factory PolyEditor))
(ui-amap {:zoom 12.5 :center map-center}
                               (ui-amap-polygon {:path polygon-path}
                                                (ui-amap-polyeditor {:active true})))
with the error :
react.development.js:126 Uncaught Error: React.Children.only expected to receive a single React element child.
    at invariant (react.development.js:126)
    at Object.only (react.development.js:1263)
    at Polygon.value (index.js:178)
    at Polygon.value (index.js:190)
    at finishClassComponent (react-dom.development.js:14302)
    at updateClassComponent (react-dom.development.js:14265)
    at beginWork (react-dom.development.js:15083)
    at performUnitOfWork (react-dom.development.js:17821)
    at workLoop (react-dom.development.js:17861)
    at HTMLUnknownElement.callCallback (react-dom.development.js:150)
(edited)

eric.shao15:12:21

I figured http://out.It is my factory function. I should use js/React.createElement instead of dom/create-element.

(defn component-factory [component]
  (fn [props & children]
    (apply dom/create-element component (clj->js props) children)))

(defn component-factory [component]
  (fn [props & children]
    (apply js/React.createElement component (clj->js props) children)))

currentoor21:12:10

has anyone used getDerivedStateFromError with fulcro?

currentoor21:12:01

I tried doing this

(defprotocol IErrorHandling
  (getDerivedStateFromError [error]))

(defsc Foo [this props]
  {:protocols (Object
                static IErrorHandling
                (getDerivedStateFromError [error]
                  {:has-error true}))}
  "test")

currentoor21:12:08

but i’m getting a complier exception

wilkerlucio21:12:52

@currentoor defsc already supports it, from the docs: :getDerivedStateFromProps (fn [props state] ...)

wilkerlucio21:12:14

;; ADDED for React 16:
      :componentDidCatch         (fn [error info] ...)
      :getSnapshotBeforeUpdate   (fn [prevProps prevState] ...)
      :getDerivedStateFromProps  (fn [props state] ...)

currentoor21:12:30

lol i couldn’t find it in the book, thanks!

currentoor21:12:49

it did seem like something that should be built in 😅

wilkerlucio21:12:50

remember to check the source docs, they usually have good things 😉

wilkerlucio21:12:01

and are the most updated usually

currentoor21:12:40

i tried to search the repo on github but maybe that was just github search being sucky

currentoor21:12:44

@wilkerlucio that’s getDerivedStateFromProps not getDerivedStateFromError

currentoor21:12:49

are they the same?

wilkerlucio21:12:23

but if you need some extra that's not in the list you should use the Object protocol to add

currentoor21:12:58

I tried that but it wasn’t working

wilkerlucio21:12:13

(defsc Foo [this props]
  {:protocols (Object
                (getDerivedStateFromError [this error]
                  {:has-error true}))}
  "test")

currentoor21:12:34

oh Object is the protocol

currentoor22:12:21

that puts it on the instance

currentoor22:12:27

whereas i need it to be static

currentoor22:12:59

i’ll try prepending static

currentoor22:12:03

@wilkerlucio i tried this

(defsc Foo [this props]
  {:protocols (static Object
                (getDerivedStateFromError [this error]
                  {:has-error true}))}
  "test")

currentoor22:12:19

but react is still giving me this warning Warning: ucv.ui.order-flow.refunds.ui/OrderRefund: getDerivedStateFromError() is defined as an instance method and will be ignored. Instead, declare it as a static method.

wilkerlucio22:12:09

not sure how to add that, but if it's a method on the class you can try to hack with: (gobj/set Foo "getDerivedStateFromError" (fn [error] ...))

currentoor22:12:31

such hack wow lol

currentoor22:12:06

no luck 🙁

currentoor22:12:24

and seeing how @tony.kay did it in fulcro, seems like it won’t be that straightforward

#?(:clj
   (defn- make-static-lifecycle [options]
     (when (contains? options :getDerivedStateFromProps)
       (let [lambda (get options :getDerivedStateFromProps)]
         ['static 'field 'getDerivedStateFromProps `(fn [p# s#]
                                                      (let [fp#        (goog.object/get p# "fulcro$value")
                                                            fs#        (goog.object/get s# "fulcro$state")
                                                            new-state# (merge fs# (~lambda fp# fs#))]
                                                        (cljs.core/js-obj "fulcro$state" new-state#)))]))))