我有一个输入组件,它将url作为输入并解析它(resolve =以某种方式获取该URL的预览):
var resolver = require('resolver');
var UrlResolver = React.createClass({
statics: {
storeListeners: {
onResolverStore: [ ResolverStore ]
}
},
getInitialState: function() {
return { value: '', resolves: [] };
},
onResolverStore: function(data) {
var resolves = [].concat(this.state.resolves, data);
this.setState({ resolves: resolves });
},
handleChange: function(event) {
var value = event.target.value;
this.setState({ value: value });
this.executeAction(resolver, value);
},
render: function () {
return (
<input value={ this.state.value } onChange={ this.handleChange } />
{
this.state.resolves.map(function(data) {
return <ResolveView data={ data } />;
});
}
);
}
});
如您所见,UrlResolver等待ResolverStore上的更改。当输入发生变化时,可能会发生这种变化。 我的问题是我的视图中有10个UrlResolvers。在这种情况下,一个输入上的任何更改都将更改ResolverStore,这将触发10个不同的事件,因此10个不同的setStates将导致10次重新渲染。所有这一切,只有一个输入应该处理这种变化。这样,9个组件也将添加不属于它们的解析数据。
这种需求的解决方案是什么?
答案 0 :(得分:0)
您似乎正在使用将数据从存储推送到组件的Flux实现,该实现采用商店正在包装的所有状态并将其推送到组件状态。当不同的组件只对该数据的子集感兴趣,或者需要首先查询数据时,这就成了一个问题。
我对Flux的看法是数据应该来自商店的组件,而不是相反。这样,您可以在组件中获得您感兴趣的数据的完全灵活性,而不会丢失单向数据流。
一个例子是:
var MyComponent = React.createClass({
getInitialState() {
return {
items: []
};
},
componentWillMount() {
MyStore.on('change', this.loadItems);
this.loadItems();
},
componentWillUnmount() {
MyStore.off('change', this.loadItems);
},
loadItems() {
MyStore.find(/* search params or find by id goes here */)
.then(items => this.setState({items: items}));
},
render() {
return (
<ul>
{this.state.items.map(item => <li>{item}</li>)}
</ul>
<button onClick={e => MyActions.add()}>Add new stuff</button>
);
}
});
如您所见,由组件查询组件感兴趣的任何数据,由组件决定,但组件仍然订阅对商店中状态的任何更改。在这个例子中,它是一个项目数组,但它也可以是由作为prop传递给组件的id获取的单个项目。
如果你在内存中拥有所有状态,那么推送商店的整个状态会很好,但是对于由REST API或WebSQL / IndexedDB数据库支持的商店,我觉得这个模型更简单。
<强> 修改 强>
进一步明确为什么我更倾向于从商店推出而不是推送到组件。通过让组件只获取它所需的数据而不是让商店将整个状态推送给你,可以更容易地看出它是否值得重新渲染。
在我的示例中,一旦调用操作,它就会在每个组件实例中调用loadItems
,但是通过从存储中拉出,您可以通过检查数据是否让组件短路该组件感兴趣已更改。这可以通过让您的商店使用不可变数据来完成,这意味着您可以使用引用相等来确定某些内容是否已更改。另一种选择是传递更改事件中实际更改的内容。然后,组件可以检查更改的项目的ID是否是它关心的内容,如果不是,则跳过重新呈现。
我会建议不要进行这样的检查,因为很容易陷入组件的陷阱,知道它是否应该重新渲染。如果您改为从商店中返回不可变列表/记录/映射,那么它只是对返回的内容进行相等性检查,如果组件感兴趣的内容发生了变化,那么它以前必须知道的内容。