"React Goes Big"
var NumberSelector = React.createClass({
render: function() {
return (
<div>
<p>You selected: Nothing</p>
<select>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</div>
)
},
})
var NumberSelector = React.createClass({
getInitialState: function() {
return {
selectedValue: 1
}
},
render: function() {
return (
<div>
<p>You selected: {this.state.selectedValue}</p>
<select value={this.state.selectedValue}>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</div>
)
},
})
var NumberSelector = React.createClass({
getInitialState: function() {
return {
selectedValue: 1
}
},
render: function() {
return (
<div>
<p>You selected: {this.state.selectedValue}</p>
<select
value={this.state.selectedValue}
onChange={this.handleChange}
>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</div>
)
},
handleChange: function(ev) {
this.setState({
selectedValue: ev.target.value
})
}
})
One-way data flow inside a component
State
DOM
Tree
Events
Stores
View
(React.js)
Actions
Actions
View
(React)
var SelectedValueStore = {
}
/* storage */
_value: 1,
getValue: function() {
return this._value
},
/* event emitter */
_handlers: [],
addChangeHandler: function(func) {
this._handlers.push(func)
},
removeChangeHandler: function(func) {
var idx = this._handlers.indexOf(func)
this._handlers.splice(idx, 1)
},
emitChange: function() {
this._handlers.forEach(function(func){ func() })
},
var NumberSelector = React.createClass({
})
/* subscribe to change events (and unsubscribe): */
componentWillMount: function() {
SelectedValueStore.addChangeHandler(this._handleValueChanged)
},
componentWillUnmount: function() {
SelectedValueStore.removeChangeHandler(this._handleValueChanged)
},
/* read state from store: */
getInitialState: function() {
return {
selectedValue: SelectedValueStore.getValue()
}
},
render: function() {
/* render stays the same :D */
},
/* handle change events by re-reading from store: */
_handleValueChanged: function() {
this.setState({
selectedValue: SelectedValueStore.getValue()
})
},
/* this is Facebook's dispatcher */
var valueDispatcher = new Flux.Dispatcher()
var ValueSelectionActions = {
/* this function creates a VALUE_WAS_SELECTED action: */
valueWasSelected: function(value) {
},
}
var action = {
actionType: "VALUE_WAS_SELECTED",
value: value,
}
valueDispatcher.dispatch(action)
/* make a handler */
var SelectedValueStore = {
// ...
_actionHandler: function(payload) {
if (payload.actionType == "VALUE_WAS_SELECTED") {
this._value = payload.value // update state
this.emitChange() // broadcast changes
}
},
}
/* hook up the store */
var boundCallback = SelectedValueStore._eventHandler.bind(SelectedValueStore)
valueDispatcher.register(boundCallback)
/* trigger the action from the view: */
var NumberSelector = React.createClass({
// ...
handleChange: function(ev) {
},
})
Views trigger application actions in response to user input
// don't set local state,
// instead, trigger event for the whole application
ValueSelectionActions.valueWasSelected(ev.target.value)
Robert Mosolgo
Full Stack, March 12, 2015