简体   繁体   English

Rxjs反应文本输入组件

[英]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高阶组件包装此组件,使用handleraperture处理副作用,如下所示:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM