使用 debounce 将 React 状态同步到 Meteor 集合

Sync React state to Meteor collection using debounce

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

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

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

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

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

问题:

如果另一个客户端更新了集合,我希望文本框显示更新后的值。为此,我必须在 getMeteorData() 函数中更新 this.state,但这是不允许的,并且出现错误:"Calling setState inside getMeteorData can result in infinite loop".

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

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

我会完全摆脱 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)中的数据是通过向下传递的 props 同步的,theComponent 通过 prop transition 知道同步。

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)以保存数据传输。