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