Skip to content

Instantly share code, notes, and snippets.

@Jessidhia
Last active August 3, 2016 01:27
Show Gist options
  • Save Jessidhia/0ce87560e4b3c93cd77475fdcf94b610 to your computer and use it in GitHub Desktop.
Save Jessidhia/0ce87560e4b3c93cd77475fdcf94b610 to your computer and use it in GitHub Desktop.
import React from 'react'
import classNames from 'classnames'
// I am trying to write a React version of an internal library's component.
// They share the CSS and class names, so the internal library's jquery event handler will capture clicks,
// thus I have to use a ref and attach handlers directly to it.
class Test extends React.Component {
constructor (props) {
super(props)
this.state = {
on: props.initialOn
}
this.handler = this.handler.bind(this)
}
toggle () {
const { state: { on } } = this
// With neither react-hot-loader/babel or transform-es2015-classes: works
// With both react-hot-loader/babel and transform-es2015-classes: works
// With react-hot-loader/babel but not transform-es2015-classes: "Can only update a mounted or mounting component."
// Moving the "this.handler = this.handler.bind(this)" to componentDidMount makes it work on all cases
this.setState({
on: !on
})
}
handler (e) {
e.stopPropagation() // stop the other library's event handler
this.toggle()
}
componentDidMount () {
this.ref.addEventListener('click', this.handler)
}
componentWillUnmount () {
this.ref.removeEventListener('click', this.handler)
}
render () {
const {
props: { name, children },
state: { on }
} = this
const classes = classNames('_ui-switch', {
'on': on,
'off': !on
})
return (
// to run before the other library, must add event directly to the DOM node instead of using onClick
<div className={classes} ref={(ref) => { this.ref = ref }}>
<span className='label'>{children}</span>
<span className='toggle-switch'>
<span className='switch'/>
</span>
{/* Warning about "changing an uncontrolled input" will be fixed in v15.2 */}
<input type='checkbox' name={name} checked={on} readOnly/>
</div>
)
}
}
Test.propTypes = {
initialOn: React.PropTypes.bool,
name: React.PropTypes.string.isRequired,
children: React.PropTypes.node.isRequired // contents of the label
}
import $ from 'jquery'
import ReactDOM from 'react-dom'
$(() => {
const el = $('<div></div>').prependTo(document.body).get(0)
ReactDOM.render(<Test name='switch' initialOn={true}>switch</Test>, el)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment