I want to do something like this
var App = React.createClass({
render: function() {
return (
)
You shouldn't be making any ajax calls in the autocomplete component (since you said you want to make it reusable). I usually put all the data request calls/api usage into a separate module that uses promises to prevent the multiple requests
So the idea then is to just have your autocomplete component get the options/data from a parent component. That parent component can get the data from store initially, and listen for any change events in that store, and update its state if needed. Pass that this.state.options
(or whatever state you're using for the options) as a prop to AutoComplete. When a user types something, emit an action with the query. That action in turns should call the API and Dispatcher, updates the store, and emits a change event for the store. Your parent component will update its state respectively, and that will flow to the AutoComplete component as prop.
So something like this:
var App = React.createClass({
getInitialState: function() {
return {
// default results/data?
data : Store.getResults('')
};
},
storeChangeListener: function(newData) {
this.setState({
data: newData
});
},
componentDidMount: function() {
this.listenTo(Store, this.storeChangeListener);
},
onChange: function(query) {
// on search change
Actions.getResults(query);
},
render: function() {
return (
<AutoComplete data={this.state.data} onChange={this.onChange} />
);
}
});
And in store, something like this:
var countryAPI = require('./countryAPI')
var Store = {
getResults: function(query) {
// check cache if any? otherwise make call
if(this.cache[query]) {
return this.cache[query];
} else {
countryAPI.search(query).then(this.update);
}
},
update: function(data) {
AppDispatcher.dispatch({
type: "DATA_FROM_SERVER",
payload: {id: query, data: result}
})
},
handleDataFromServer: function(action) {
//store into cache/store
this.cache[action.payload.id] = action.payload.result;
this.emit("change"); // re-render app on whoever is listening to this store
}
}
and your api for example
var countryAPI = {
search: function(query) {
// check to make sure this promise isnt called before
if(!this.allPromises[query]) {
this.allPromises[query] = $.ajax({
url: '/country' + '?search=' + country
})
}
return this.allPromises[query];
}
}
To sum it up, the actual API implementation imo should be separated from flux actions, they only should be concerned with Web-API specific stuff and just let flux actions/stores handle the responses separately as data flows:
Component --> Listens to Store
--> Calls Load Action --> Show Pending State/Optimistic Updates --> Dispatcher --> Store --> changeEvent (Component will be listening and be updated)
--> countryAPI.load()
onLoadSuccess --> Dispatcher --> Store --> changeEvent --> Component
onLoadError --> Dispatcher --> Store --> changeEvent --> Component