Skip to content

Instantly share code, notes, and snippets.

@danschumann
Last active August 29, 2015 14:10
Show Gist options
  • Save danschumann/34841fb65e9eaf625139 to your computer and use it in GitHub Desktop.
Save danschumann/34841fb65e9eaf625139 to your computer and use it in GitHub Desktop.
Coffeescript react class wrapper
diagnoser = null
$ =>
(diagnoser = new Diagnoser).renderTo $(".diagnoser")[0]
console.log "DIAG", diagnoser
class ReactClass
value: 'asdf123'
birth: (Class) =>
console.log 'that', this
(options) =>
console.log 'huh', this
if (ref = options?.ref) and (ref = @ref(ref)) and ref instanceof Class
ref.Factory options
else
c = (new Class options)
#c.Factory.instance = c
c.Factory.apply this, arguments
renderTo: (dom) ->
el = React.createElement(@React)
@render(false) # can't force update yet
React.render el, dom
ref: (key) =>
@react.refs[key]?.instance
constructor: (@options) ->
console.log @constructor
s = _.object _.compact _.map @constructor.prototype, (method, key) =>
return if key is 'constructor'
[key, if _.isFunction(method) then _.bind(method, this) else method]
self = this
s.componentWillMount = ->
console.log 'food', this, @props
self.props = (@props ?= {})
self.react = this
@instance = self
s.getInitialState ?= ->
self.state ? {}
s.render = s.template
console.log @, @constructor::
@React ?= React.createClass(s)
@Factory ?= React.createFactory(@React)
render: (forceUpdate) ->
console.log this, @props
@react.forceUpdate() if forceUpdate isnt false
valueLink: (attr) ->
value: @state[attr]
requestChange: (newVal) =>
@state[attr] = newVal
@render()
class Diagnoser extends ReactClass
displayName: 'Diagnoser'
constructor: ->
@state = {
caliber: 2
muzzle_velocity: 3000
}
super
@sub = new SubClass
@sub2 = new SubClass
@hello = 'hi'
mixins: [React.addons.LinkedStateMixin]
click: =>
@hello = 'HELLO!'
@render()
renderContents: ->
_.map @state, (val, attr) =>
<div className="form-group" key={attr}>
<h1 onClick={@click}>{@hello}</h1>
<label className="control-label col-xs-6">
{attr}
</label>
<div className="col-xs-6">
<input className="form-control" valueLink={@valueLink attr} />
</div>
</div>
render: ->
super
clearInterval @Inty
@Inty = setInterval =>
console.log @react.refs, @ref('hi3'), @ref('hi3').qux
@sub.qux += '1'
@ref('hi3').qux = @ref('hi3').qux + 1
@ref('hi3').props.food += '1'
@ref('hi3').render()
, 2000
clearInterval @Inty3
@Inty3 = setInterval =>
@render()
, 5000
template: ->
<div>
<div className="section-header">
Diagnoser
</div>
<div className="panel panel-default form form-horizontal">
<div className="panel-heading">
Inputs
</div>
<div className="panel-body">
<div>
{@renderContents()}
</div>
<div>
<@sub.Factory ref="hi" food='testme' ham="true" />
<@sub2.Factory ref="hi2" food="tester2" />
{Class = @birth SubClass}
<Class ref="hi3" food="tester3" />
</div>
</div>
</div>
clicked kid = {'' + !!@props.clickedChild}
</div>
class SubClass extends ReactClass
displayName: 'Sub'
constructor: ->
@state = {
foo: 'bar'
}
super
@qux = 'quo'
mixins: [React.addons.LinkedStateMixin]
click: =>
@qux = 'lazidor'
console.log 'click', @props
diagnoser.props.clickedChild = true
@render()
template: ->
<div>
<div className="section-header" onClick={@click}>
{@qux}
</div>
<div className="">
ham: {@props.ham}
<br />
food: {@props.food}
</div>
</div>
@danschumann
Copy link
Author

calling diagnoser.render() will work, making it less reactive to the inside of itself, and more reactive to the programmer callign render on it.

IMO this syntax is better than Reacts.

I plan on adding events to trigger, so you can listen to any and all of them, over react's function based callbacks ( componentWillmount )

If you override Diagnoser::render, you must call super to trigger react to forceUpdate and thus update the DOM.

Overall, I really like react, and really hate it, this hopefully will solve the latter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment