Skip to content

Instantly share code, notes, and snippets.

@miku
Forked from pk11/reactjs.js
Created March 26, 2014 09:21
Show Gist options
  • Save miku/9779527 to your computer and use it in GitHub Desktop.
Save miku/9779527 to your computer and use it in GitHub Desktop.
/** @jsx React.DOM */
/**
* Our component structure will look like the following:
* - WikiBox
* -- AutoCompleteBox
* --- AutoComplete
*/
// this component renders a single entity coming from wikipedia
var AutoComplete = React.createClass({
render: function() {
return (
<p>{this.props.name}</p>
);
}
});
/**
* this component is the parent of AutoComplete
*/
var AutoCompleteBox = React.createClass({
render: function() {
//note: we are producing a new immutable array here
var nodes = this.props.list.map(function(item){
return <AutoComplete name={item} />;
});
return (
<div className="autocompleteNodes">
//we need to convert our immutable array back to mutable since React only can deal with standard arrays
{nodes.mutable()}
</div>
);
}
});
/**
* The main action is happening here
*/
var WikiBox = React.createClass({
//we initilize the component state with an immutable array
getInitialState: function() {
return {autocomplete: immutable.array([]), call: {latest:0, term:''}};
},
makeCall: function(term, current) {
var wikiUrl = "http://en.wikipedia.org/w/api.php?action=opensearch&format=json&callback=?&search="+encodeURIComponent(term);
$.getJSON(wikiUrl, function(data) {
// this ensures that we ignore out of order ajax calls and that the last call will win.
//Note: an alternative could have been to use jquery's beforeSend callback to abort the previous call
//but that would have required an enclosing mutable reference to the previous XHR object.
if (current == this.state.call.latest) {
var newPriority = this.state.call.latest - 1;
this.setState({autocomplete: immutable.array(data[1]), call: {latest: newPriority, term:''} });
}
}.bind(this)
);
},
//set state if user enters at least 3 chars, also reset state if user clears input box.
handleKeyUp : function (e) {
var k = e.target.value;
if (k.length > 3 ) {
var priority = this.state.call.latest+1;
this.setState({call: {latest: priority, term: k }});
}
if (k.length == 0 && this.state.autocomplete.length > 0 ) {
this.setState({autocomplete: immutable.array([]), call: {latest:0, term:''}});
}
return false;
},
render: function() {
// if the incoming state contains a search term with a real priority then make the async ajax/jsonp calls
if (this.state.call.latest > 0 && this.state.call.term != '') {
this.makeCall(this.state.call.term, this.state.call.latest);
}
return (
<div className="wikibox">
<span>Give it a try:</span>
<input type="text" placeholder="search" onKeyUp={this.handleKeyUp} />
<AutoCompleteBox list={this.state.autocomplete} />
</div>
);
}
});
/**
* Boostrapping component.
* It also attaches React to the root div called `container`.
*/
React.renderComponent(
<WikiBox />,
document.getElementById('container')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment