将函数传递给 ClojureScript 中包装的 React 组件

Passing a function to a wrapped React component in ClojureScript

我正在尝试在 clojurescript 中使用包 react-dropzone

原始 javascipt 代码具有作为包装组件的子项的功能:

import React from 'react'
import Dropzone from 'react-dropzone'

<Dropzone onDrop={acceptedFiles => console.log(acceptedFiles)}>
  {({getRootProps, getInputProps}) => (
    <section>
      <div {...getRootProps()}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>
    </section>
  )}
</Dropzone>

我试过将其转换为:

(ns test.dropzone
  (:require ["react" :as react]
            ["react-dropzone" :default Dropzone]))


(defn file-dropzone []
  [:> Dropzone {:on-drop #(js/alert "Drop")}
   (fn [getRootProps getInputProps]
     [:section
      [:div
       [:p "Drop"]]])])

但是 returns 这个错误:

Error: Objects are not valid as a React child (found: object with keys {ns, name, fqn, _hash, cljs$lang$protocol_mask$partition0$, cljs$lang$protocol_mask$partition1$}). If you meant to render a collection of children, use an array instead.
    in Dropzone (created by grafitch.dropzone.file_dropzone)
    in grafitch.dropzone.file_dropzone (created by upload-test-page)
    in div (created by upload-test-page)
    in div (created by upload-test-page)
    in div (created by upload-test-page)
    in section (created by upload-test-page)
    in upload-test-page (created by page)
    in div (created by page)
    in page

这如何在 clojurescript 中完成?

我认为您收到此错误的原因是因为您的内部函数的结果实际上是 PersistentVector 而不是 React 组件。用试剂包裹函数的结果。core/as-element.

我用 helix 将反应代码翻译成 clojurescript。我不知道如何使用试剂来做到这一点。

解决方法:

(ns test.dropzone
  (:require
   [helix.core :refer [defnc $]]
   [helix.dom :as d]
   ["react-dropzone" :as dz :default Dropzone :refer [useDropzone]]))


(defnc file-dropzone []
  ($ Dropzone {:onDrop (fn [accepted-files] (.log js/console accepted-files))}
     (fn [dropzone-obj]
       (let [[getRootProps getInputProps]
             (as-> dropzone-obj obj [(.-getRootProps obj) (.-getInputProps obj)])]
         (d/section
          (d/div {:& (getRootProps)}
                 (d/input {:& (getInputProps)})
                 (d/p "Drag 'n' drop some files here, or click to select files")))))))

我差点用试剂做到了。

(ns test.dropzone
  (:require
   ["react-dropzone" :refer [useDropzone]]))

(defn dropzone []
  (let [props (useDropzone)
        get-input-props (.-getInputProps props)
        get-root-props (.-getRootProps props)]
    
    (r/as-element
     [:section.container
      [:div.dropzone (js->clj (get-root-props #_(clj->js {:onClick #(js/alert "Click")})) :keywordize-keys true)
       [:input (js->clj (get-input-props) :keywordize-keys true)]
       [:p "my dropzone"]]])))

并通过

调用它
[:> dropzone]

但似乎 ref.

仍然存在一些问题

当我添加一些自己的 onClick 或 onDrop 操作时(如在评论部分),它会起作用,但如果没有它,点击或放下时不会发生任何事情。