我想做这样的事情
var App = React.createClass({ render: function() { return ( <CountryAutoComplete /> ) } });
不同的应用
var App2 = React.createClass({ render: function() { return ( <CountryAutoComplete /> ) } });
这是一个简单的自动完成功能(不是整个文件)
var AutoComplete = React.createClass({ componentDidMount: function() { $(this.getDOMNode()).typeahead(this.props); }, render: function() { return ( <input type="text" class="typeahead" onChange={this.props.onChange} /> ); } });
CountryAutoComplete就像这样的东西是自包含的。
var CountryAutoComplete = React.createClass({ search: function(country, process) { // Make an ajax call and return the data. No other components needed $.ajax({ url: '/country' + '?search=' + country }).then(process); }, render: function() { return ( <AutoComplete onChange={this.props.onChange} source={this.search} /> ); } });
根据Flux文档,看起来需要API调用的所有内容都需要经过
操作-> API->调度程序->存储->组件
这使得CountryAutoComplete绑定到特定的应用程序,因为操作,分派器和存储都特定于该应用程序。使该组件在应用程序之间可重用的最佳方法是什么?
您不应该在自动完成组件中进行任何Ajax调用(因为您说过要使其可重用)。我通常将所有数据请求调用/ api用法放在一个单独的模块中,该模块使用promise防止多个请求
因此,想法是让您的自动完成组件从父组件获取选项/数据。该父组件可以最初从存储中获取数据,并监听该存储中的任何更改事件,并在需要时更新其状态。将其this.state.options(或用于选项的任何状态)传递为自动完成的道具。用户键入内容时,对查询发出操作。相应地,该操作应调用API和分派器,更新商店,并为商店发出更改事件。您的父组件将分别更新其状态,并且将作为道具流向AutoComplete组件。
this.state.options
所以像这样:
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} /> ); } });
在商店中,如下所示:
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 } }
和您的api例如
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