我有以下反应组件
<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 });
}
如何在rxjs上使用去抖动?
答案 0 :(得分:15)
你需要从变化事件(例如使用主题)中创造出可观察性,然后对其进行去抖动。
以下是适合您的全功能示例:
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>
答案 1 :(得分:1)
这将是Refract的好用例!
第一步是将输入拉到一个单独的组件中
const Input = ({ onChange, value }) => (
<input type="text" value={value} onChange={onChange} />
)
下一步是用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)
aperture
可让您观察组件的道具。在这种情况下,观察value
属性很有意义-每次value
更改时,component.observe('value')
流都会获得一个新值。
handler
是一个由光圈流输出的每个值调用的函数。在这种情况下,去抖动的值会直接传递到名为onUpdate
的新道具。
文档中详细说明了光圈和处理程序-Observing React介绍了光圈,Handling Effects说明了处理程序。
作为如何使用此示例:
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>
)
}
}
使用此代码,文本DebouncedInput
将立即显示用户的输入(这是UX的理想选择),同时消除了调用onUpdate
回调的副作用。然后,将这个onUpdate
暴露给消耗Search
组件的组件就变得微不足道了!
答案 2 :(得分:0)
我同意Oles Savluk的例子。另外,我将从组件中提取主题逻辑。它不需要位于组件内部,因为它没有状态,而且我认为这也使组件更易于理解。
也:此示例已更新为使用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>