[英]Rxjs debounce on react text input component
I have the following react component 我有以下反应组件
<input className={styles.incSrchTextBox} type="text" name="search" placeholder="Search.."
onChange={this.onChange} />
onChange(e) {
const newText = e.target.value;
console.log(newText);
this.setState({ searchText: newText });
}
How do I use debounce on rxjs on this? 我如何在rxjs上使用debounce?
You will need to cretae observable from change events(for example using Subject) and then debounce on that. 你需要从变化事件(例如使用主题)中创建可观察的,然后对其进行去抖动。
Here is the fully featured example for you: 以下是适合您的全功能示例:
class Search extends React.Component { constructor(props) { super(props); this.state = { search: '', debounced: '', }; this.onSearch$ = new Rx.Subject(); this.onSearch = this.onSearch.bind(this); } componentDidMount(){ this.subscription = this.onSearch$ .debounceTime(300) .subscribe(debounced => this.setState({ debounced })); } componentWillUnmount() { if (this.subscription) { this.subscription.unsubscribe(); } } onSearch(e) { const search = e.target.value; this.setState({ search }); this.onSearch$.next(search); } render() { const { search, debounced } = this.state; return ( <div> <input type="text" value={search} onChange={this.onSearch} /> <div>debounced value: {debounced}</div> </div> ); } } ReactDOM.render( <Search />, document.getElementById('root') );
<script src="https://unpkg.com/rxjs@5.4.0/bundles/Rx.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>
This would be a good use case for Refract ! 这对于Refract来说是一个很好的用例!
The first step would be to pull the input out into a separate component: 第一步是将输入拉入一个单独的组件:
const Input = ({ onChange, value }) => (
<input type="text" value={value} onChange={onChange} />
)
Next step would be to wrap this component with Refract's withEffects
higher-order component, with a handler
and an aperture
to handle the side-effects like this: 下一步是使用Refract的withEffects
高阶组件包装此组件,使用handler
和aperture
处理副作用,如下所示:
import { withEffects } from 'refract-rxjs'
import { debounceTime } from 'rxjs/operators'
const Input = ({ onChange, value }) => (
<input type="text" value={value} onChange={onChange} />
)
const aperture = () => component =>
component.observe('value').pipe(debounceTime(300))
const handler = ({ onUpdate }) => value => onUpdate(value)
const DebouncedInput = withEffects(handler)(aperture)(Input)
An aperture
lets you observe your component's props. aperture
可让您观察组件的道具。 In this case, it would make sense to observe the value
prop - every time the value
changes, the component.observe('value')
stream gets a new value. 在这种情况下,观察value
prop是有意义的 - 每次value
更改时, component.observe('value')
流都会获得一个新值。
The handler
is a function called with each value output by the aperture's stream. handler
是一个函数,通过光圈的流输出每个值。 In this case, the debounced value is passed straight through to a new prop called onUpdate
. 在这种情况下,去抖动值直接传递给名为onUpdate
的新道具。
Both apertures and handlers are explained in detail in the docs - Observing React introduces apertures, and Handling Effects explains handlers. 文档中详细解释了孔径和处理程序 - Observing React引入了孔径, 处理效果解释了处理程序。
As an example of how you would use this: 作为如何使用它的一个例子:
class Search extends React.Component {
state = { debounced: '', search: '' }
onSearch = e => this.setState({ search: e.target.value })
onUpdate = debounced => this.setState({ debounced })
render() {
return (
<div>
<DebouncedInput
type="text"
value={this.state.search}
onChange={this.onSearch}
onUpdate={this.onUpdate}
/>
<div>debounced value: {debounced}</div>
</div>
)
}
}
With this code, the text DebouncedInput
would display the user's input instantly (which is ideal for UX), while debouncing the side-effect of calling the onUpdate
callback. 使用此代码,文本DebouncedInput
将立即显示用户的输入(这是UX的理想选择),同时消除调用onUpdate
回调的副作用。 It would then be trivial to expose this onUpdate
to components which consume the Search
component! 然后将这个onUpdate
公开给使用Search
组件的组件是微不足道的!
I agree with the example by Oles Savluk. 我同意Oles Savluk的例子。 In addition, I would extract the Subject logic out of the component. 另外,我会从组件中提取主题逻辑。 It doesn't need to live inside the component, as it has no state, and I think this also makes the component easier to understand. 它不需要存在于组件内部,因为它没有状态,我认为这也使组件更容易理解。
Also: The example is updated to use RxJS 6.2.2 另外:更新示例以使用RxJS 6.2.2
const { Subject } = rxjs; const { debounceTime } = rxjs.operators; const onSearch$ = new rxjs.Subject().pipe( debounceTime(300) ); class Search extends React.Component { constructor(props) { super(props); this.state = { search: '', debounced: '', }; } componentDidMount(){ this.subscription = onSearch$.subscribe( debounced => this.setState({ debounced }) ); } componentWillUnmount() { if (this.subscription) { this.subscription.unsubscribe(); } } onSearch = (e) => { const search = e.target.value; this.setState({ search }); onSearch$.next(search); } render() { const { search, debounced } = this.state; return ( <div> <input type="text" value={search} onChange={this.onSearch} /> <div>debounced value: {debounced}</div> </div> ); } } ReactDOM.render( <Search />, document.getElementById('root') );
<script src="https://unpkg.com/rxjs@6.2.2/bundles/rxjs.umd.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.