Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extends React.Component directly without create-react-class #416

Merged
merged 3 commits into from Dec 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
**[compare](https://github.com/reagent-project/reagent/compare/v0.8.1...master)**

- Fix using metadata to set React key with Fragment shortcut (`:<>`) ([#401](https://github.com/reagent-project/reagent/issues/401))
- Create React Component without `create-react-class`

## 0.8.1 (2018-05-15)

Expand Down
48 changes: 39 additions & 9 deletions src/reagent/impl/component.cljs
@@ -1,5 +1,5 @@
(ns reagent.impl.component
(:require [create-react-class :as create-react-class]
(:require [goog.object :as gobj]
[react :as react]
[reagent.impl.util :as util]
[reagent.impl.batching :as batch]
Expand Down Expand Up @@ -156,9 +156,10 @@
:getDefaultProps
(throw (js/Error. "getDefaultProps not supported"))

;; In ES6 React, this is now part of the constructor
:getInitialState
(fn getInitialState []
(this-as c (reset! (state-atom c) (.call f c c))))
(fn getInitialState [c]
(reset! (state-atom c) (.call f c c)))

:componentWillReceiveProps
(fn componentWillReceiveProps [nextprops]
Expand Down Expand Up @@ -257,7 +258,6 @@
{} fmap)]
(assoc fmap
:displayName name
:autobind false
:cljsLegacyRender legacy-render
:reagentRender render-fun
:render (:render static-fns))))
Expand All @@ -272,14 +272,44 @@
(-> body
camelify-map-keys
add-obligatory
wrap-funs
map-to-js))
wrap-funs))

;; Credits to Paulus Esterhazy, Thomas Heller
;; https://gist.github.com/pesterhazy/2a25c82db0519a28e415b40481f84554
;; https://gist.github.com/thheller/7f530b34de1c44589f4e0671e1ef7533#file-es6-class-cljs-L18
(defn make-component
"Creates a React Component class
`m` is a js-obj of class methods
`s` is a js-obj of static methods"
([display-name m s] (make-component display-name nil m s))
([display-name construct m s]
(let [cmp (fn [props context updater]
(cljs.core/this-as this
(.call react/Component this props context updater)
(when construct
(construct this))
this))]
(gobj/extend (.-prototype cmp) (.-prototype react/Component) m)
(gobj/extend cmp react/Component s)

(when display-name
(set! (.-displayName cmp) display-name)
(set! (.-cljs$lang$ctorStr cmp) display-name)
(set! (.-cljs$lang$ctorPrWriter cmp)
(fn [this writer opt]
(cljs.core/-write writer display-name))))
(set! (.-cljs$lang$type cmp) true)
(set! (.. cmp -prototype -constructor) cmp))))

(defn create-class [body]
{:pre [(map? body)]}
(->> body
cljsify
create-react-class))
(let [body (cljsify body)
m (dissoc body :displayName :getInitialState :contextTypes :childContextTypes)
s (select-keys body [:childContextTypes :contextTypes])]
(make-component (:displayName body)
(:getInitialState body)
(map-to-js m)
(map-to-js s))))

(defn fiber-component-path [fiber]
(let [name (some-> fiber
Expand Down