You could create a reagent component, export it, and then import it in your JS code.
Since you already have webpack/react in your js project, you need to exclude those from your cljs project:
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.229"]
[org.clojure/core.async "0.2.391"
:exclusions [org.clojure/tools.reader]]
[reagent "0.6.0" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server]]]
Now you have to trick Reagent into thinking that those react files you've just excluded are still here. Create these three files:
src/cljsjs/react.cljs
(ns cljsjs.react)
src/cljsjs/react/dom.cljs
(ns cljsjs.react.dom)
src/cljsjs/react/dom/server.cljs
(ns cljsjs.react.dom.server)
Yes, just one line with namespace declaration in each file.
Now you can write your component:
reagent_component/core.cljs:
(ns reagent-component.core
(:require [reagent.core :as r]))
(def counter (r/atom 5))
(def ^:export test66
(r/create-class
{:reagent-render
(fn [props]
(let [{:keys [name]} props]
[:div
{:on-click (fn [] (swap! counter inc))}
name ", I am counting " (clojure.string/join ", " (map inc (range @counter)))])
)}))
Your cljsbuild section in project.clj might look like this:
:cljsbuild {:builds
[{:id "min"
:source-paths ["src"]
:compiler {:output-to "resources/public/js/compiled/reagent_component_min.js"
:output-dir "resources/public/js/compiled/min"
:main reagent-component.core
:optimizations :advanced
:asset-path "js/compiled/out"
}}]}
For the purpouse of brevity I've given you only the min section of the cljsbuild.
lein cljsbuild once min will produce resources/public/js/compiled/reagent_component_min.js file, which must be copied into your Webpack project.
New entry is added to your webpack.config before your main entry point:
entry: [`${APP_DIR}/reagent_component_min.js`, `${APP_DIR}/main.js`],
This file (reagent_component_min.js) should be excluded from babelification:
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components|reagent_component_min.js)/,
loader: 'babel-loader',
query: {
presets: ['latest']
}
}
]
}
and in your javascript you use it like this:
import React from 'react';
import ReactDOM from 'react-dom';
const comp = reagent_component.core.test66;
const element = <div>Hello, world
{React.createElement(comp, {name: 'akond'})}
</div>;
ReactDOM.render(
element,
document.getElementById('app')
);
Yes, babel jsx plugin does not recognize <comp name="..."/>. That's why React.createElement is called. I didn't figure out how to make it look better, but it works.