多个组件捕获存储存储事件

时间:2015-04-17 02:46:59

标签: javascript reactjs reactjs-flux flux fluxible

我有一个输入组件,它将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个组件也将添加不属于它们的解析数据。

这种需求的解决方案是什么?

1 个答案:

答案 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是否是它关心的内容,如果不是,则跳过重新呈现。

我会建议不要进行这样的检查,因为很容易陷入组件的陷阱,知道它是否应该重新渲染。如果您改为从商店中返回不可变列表/记录/映射,那么它只是对返回的内容进行相等性检查,如果组件感兴趣的内容发生了变化,那么它以前必须知道的内容。