使用去抖动将React状态同步到Meteor集合

时间:2015-11-06 14:21:03

标签: javascript meteor reactjs debouncing

我的Meteor + React应用程序中有一个文本框。我想将其值同步到Mongo集合。但是,我不想在每次击键后更新集合,只有当用户停止键入几秒钟时才会更新。

我的render()函数中的文本框如下所示:

<input type="text" ref="answer" onChange={this.onChange} value={this.state.someValue} />

我将文本框值存储在this.state而不是this.data中,因为this.data反映的Mongo集合可能尚未更新。

到目前为止,所有这些都有效。

问题:

如果其他客户端更新了集合,我希望文本框显示更新的值。为此,我必须在this.state函数内更新getMeteorData(),但不允许这样做,我收到错误:&#34;在getMeteorData中调用setState会导致无限循环& #34;

现在我有一个解决方法,我手动更新componentDidMount()getMeteorData()中的文本框值,但它感觉很乱,我根本不喜欢它。

有更好的方法吗?如果我保证我会成为一个好孩子并且表现得很好,我可以在getMeteorData()内强制更新状态吗?

1 个答案:

答案 0 :(得分:1)

我会完全摆脱getMeteorData并转向createContainer。数据流在大多数情况下变得清晰简单,包括这种特定情况。在这里。

首先,创建一个容器来获取数据。

export default theContainer = createContainer(() => {
  // Subscribe to the publication which publishes the data.
  const subscription = Meteor.subscribe(...);
  // Derive the data for the input box and form the props to pass down.
  const props = {
    answer: getAnswer(subscription)
  };
  return props;
}, theComponent);

theContainer充当容器组件,并通过props将包含的数据传输到表示组件theComponent。请注意,赋予createContainer的函数是响应式的,这意味着对该函数中的被动数据源的更改会触发重新运行并导致重新呈现theComponent

到现在为止,我们全都武装起来。由于Mongo集合中的数据(Minimongo确切地)被传递下来的道具同步,theComponent通过道具过渡意识到同步。

export default class theComponent extends React.Component {
  ...

  componentWillReceiveProps(nextProps) {
    if (this.props.answer !== nextProps.answer) {
      this.setState({
        answer: nextProps.answer
      });
    }
  }

  render() {
    return <input value={this.state.answer} onChange={this.onChange} />;
  }
}

发生此类转换时,即将到来的值将更新为状态,此受控组件将根据更新的新值呈现输入。

另一方面,当用户开始键入时,更改处理程序this.onChange会更新用户对状态的输入,每个键提示都是一个受控组件。但是,只有在预设的持续时间已经过去以保存数据传输时,处理程序才会更新Mongo集合(再次,Minimongo)。