Skip to content

Instantly share code, notes, and snippets.

@bloodyowl

bloodyowl/00.js Secret

Created April 27, 2015 20:14
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bloodyowl/060a52ef6cfef150ddd4 to your computer and use it in GitHub Desktop.
Save bloodyowl/060a52ef6cfef150ddd4 to your computer and use it in GitHub Desktop.
/**
* how to get rid of react mixins the clean way
*
* Matthias Le Brun
*
* @bloodyowl
* @reactjsfrance
* @putaindecode
*/
/**
* how to get rid of react mixins the clean way
*
* 1. l'API .createClass
*/
import React, {PropTypes} from "react"
const Button = React.createClass({
propTypes: {
onClick: PropTypes.func,
disabled: PropTypes.bool,
},
render() {
return (
<div
disabled={this.props.disabled}
onClick={this.props.onClick}
className="pjs-Button">
{this.props.children}
</div>
)
},
})
export default Button
/**
* how to get rid of react mixins the clean way
*
* 2. mixins
*/
const LogEventMixin = {
logEvent(event) {
if(__DEV__) {
event.persist()
console.log(
`DOMEvent fired: ${ event.type }`,
event
)
}
},
}
const Button = React.createClass({
// composition
mixins: [
LogEventMixin,
],
render() {
return (
<button onClick={this.logEvent}>
{this.props.children}
</button>
)
},
})
/**
* how to get rid of react mixins the clean way
*
* 3. mixins & lifecycle
*/
import debounce from "utils/debounce"
const ResizeMixin = {
componentDidMount() {
this._handleResize =
debounce(this.handleResize, 300)
window.addEventListener(
"resize",
this._handleResize,
false
)
},
componentWillUnmount() {
window.removeEventListener(
"resize",
this._handleResize,
false
)
this._handleResize = null
},
handleResize() {
this.forceUpdate()
},
}
/**
* how to get rid of react mixins the clean way
*
* 4. mixins & too much magic
*/
const ToggleMixin = {
getInitialState() {
return {
visible: true,
}
},
show() {
this.setState({
visible: true,
})
},
hide() {
this.setState({
visible: false,
})
},
toggle() {
this.setState((state) => {
return {
visible: !state.visible,
}
})
},
}
const MyComponent = React.createClass({
mixins: [
ToggleMixin,
],
render() {
return (
<div className="pjs-MyComponent">
<button onClick={this.toggle}>
toggle
</button>
{this.state.visible &&
<div>
some content
</div>}
</div>
)
}
})
/**
* how to get rid of react mixins the clean way
*
* 5. the flux case
*/
import MyStore from "stores/MyStore"
const MyComponent = React.createClass({
mixins: [
someFluxImplem.createMixinFor(MyStore),
],
render() {
return (
<div className="pjs-MyComponent">
{this.state.value}
{/* ^ MyStore.getAll().value */}
</div>
)
}
})
/**
* how to get rid of react mixins the clean way
*
* 6. react@^0.13.0
*/
import React, {Component} from "react"
// no more mixins
// no autobinding
class MyComponent extends Component {
render() {
return (
<div className="pjs-MyComponent">
oh hai es6 classes
</div>
)
}
}
/**
* how to get rid of react mixins the clean way
*
* 7. fuck m8 how do I do
*/
import React, {Component, PropTypes} from "react"
class Button extends Component {
static propTypes = {
disabled: PropTypes.bool,
onClick: PropTypes.func,
}
handleClick(event) {
if(this.props.onClick) {
this.props.onClick(event)
}
}
render() {
return (
<button
disabled={true}
onClick={(e) => this.handleClick(e)}>
{this.props.children}
</button>
)
}
}
/**
* how to get rid of react mixins the clean way
*
* 8. how 'bout mixins
* a. no interaction with the component itself
*/
import React, {Component, PropTypes} from "react"
import logEvent from "utils/logEvent"
class Button extends Component {
render() {
return (
<button onClick={logEvent}>
{this.props.children}
</button>
)
}
}
/**
* how to get rid of react mixins the clean way
*
* 8. how 'bout mixins
* b. interacts with the component & the component
* only
*/
import React, {Component} from "react"
import debounce from "utils/debounce"
export default (C) => {
class Resizer extends Component {
componentDidMount() {
this._handleResize =
// need to use function.bind now
debounce(this.handleResize.bind(this), 300)
window.addEventListener(
"resize",
this._handleResize,
false
)
}
componentWillUnmount() {
window.removeEventListener(
"resize",
this._handleResize,
false
)
this._handleResize = null
}
handleResize() {
this.forceUpdate()
}
render() {
return (
<C {...this.props}>
{this.props.children}
</C>
)
}
}
return Resizer
}
// somewhere else
class MyComponent extends Component{
render() {
return (
<div
style={{
width:
window.innerWidth - MARGIN * 2,
}}>
hey
</div>
)
}
}
export default resizer(MyComponent)
/**
* how to get rid of react mixins the clean way
*
* 8. how 'bout mixins
* c. the stateful stuff
*/
import React, {Component} from "react"
export default (C) => {
class Toggle extends Component {
state = {
visible: true,
}
show() {
this.setState({
visible: true,
})
}
hide() {
this.setState({
visible: false,
})
}
toggle() {
this.setState((state) => {
return {
visible: !state.visible,
}
})
}
render(C) {
return (
<C
{...this.props}
{...this.state}
show={() => this.show()}
hide={() => this.hide()}
toggle={() => this.toggle()}>
{this.props.children}
</C>
)
}
}
return Toggle
}
class MyComponent extends Component {
render() {
return (
<div className="pjs-MyComponent">
<button onClick={this.props.toggle}>
toggle
</button>
{this.props.visible &&
<div>
some content
</div>}
</div>
)
}
}
export default toggle(MyComponent)
/**
* how to get rid of react mixins the clean way
*
* 8. how 'bout mixins
* d. how does it play with flux?
*/
import React, {Component} from "react"
export default (C) => {
class StoreReceiver extends Component {
static contextTypes = {
dispatcher: PropTypes.func,
}
constructor() {
this._updateStateFromStore =
this.updateStateFromStore.bind(this)
}
componentWillMount() {
this.setState({
[C.storePropName]: this.context.dispatcher
.getStore(C.storeName)state,
})
}
componentDidMount() {
this.context.dispatcher.getStore(C.storeName)
.addChangeListener(
this._updateStateFromStore
)
}
componentWillUnmount() {
this.context.dispatcher.getStore(C.storeName)
.removeChangeListener(
this._updateStateFromStore
)
}
updateStateFromStore() {
this.setState({
[C.storePropName]: this.context.dispatcher
.getStore(C.storeName).state
})
}
render() {
return (
<C {...this.props} {...this.state}>
{this.props.children}
</C>
)
}
}
}
/**
* how to get rid of react mixins the clean way
*
* 9. contexts?
*/
import React, {Component, PropTypes} from "react"
class App extends Component {
static childContextTypes = {
dispatcher: PropTypes.object,
RouteHandler: PropTypes.func,
}
static propTypes = {
dispatcher: PropTypes.object,
RouteHandler: PropTypes.func,
}
getChildContext() {
return {
dispatcher: this.props.dispatcher,
RouteHandler: this.props.RouteHandler,
}
}
render() {
return (
<div className="pjs-App">
<this.props.RouteHandler />
</div>
)
}
}
export SomeComponent extends Component {
static contextTypes = {
dispatcher: this.props.dispatcher,
}
handleClick() {
this.context.dispatcher.dispatch(
SomeAction.updateStuff({
id: this.props.id,
})
)
}
render() {
return (
<button onClick={() => this.handleClick()}>
{`do something`}
</button>
)
}
}
/**
* how to get rid of react mixins the clean way
*
* 10. contexts use cases
*/
class Container extends Component {
static childContextTypes = {
// user's rights
user: PropTypes.object,
// style variables shared with cssnext
styleVariables: PropTypes.object,
// handler from react router
RouteHandler: PropTypes.func,
// flux dispatcher which holds the stores
...Dispatcher.getContextType(),
// translations
i18n: PropTypes.object,
// form validation schemas
schemas: PropTypes.object,
}
// …
}
class SomeComponent extends Component {
static contextTypes = {
i18n: PropTypes.object,
}
render() {
const t = this.context.i18n
.createTranslator("SomeComponent")
return (
<div className="pjs-SomeComponent">
{t("HELLOWORLD")}
{t("YOU_ARE", {
n: this.props.attendees.length,
})}
</div>
)
}
}
/**
* how to get rid of react mixins the clean way
*
* merci 😄
*
* Matthias Le Brun
*
* @bloodyowl
* @reactjsfrance
* @putaindecode
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment