diff --git a/src/components/search.js b/src/components/search.js index 19992dd..fc6c5e5 100644 --- a/src/components/search.js +++ b/src/components/search.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' import { search as icons } from '../svgs' import NimbleEmojiIndex from '../utils/emoji-index/nimble-emoji-index' +import { throttleIdleTask } from '../utils/index' export default class Search extends React.PureComponent { constructor(props) { @@ -15,9 +16,11 @@ export default class Search extends React.PureComponent { this.data = props.data this.emojiIndex = new NimbleEmojiIndex(this.data) this.setRef = this.setRef.bind(this) - this.handleChange = this.handleChange.bind(this) this.clear = this.clear.bind(this) this.handleKeyUp = this.handleKeyUp.bind(this) + + // throttle keyboard input so that typing isn't delayed + this.handleChange = throttleIdleTask(this.handleChange.bind(this)) } search(value) { diff --git a/src/utils/index.js b/src/utils/index.js index 241b18b..8276184 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -189,6 +189,24 @@ function measureScrollbar() { return scrollbarWidth } +// Use requestIdleCallback() if available, else fall back to setTimeout(). +// Throttle so as not to run too frequently. +function throttleIdleTask(func) { + const queue = + typeof requestIdleCallback === 'function' ? requestIdleCallback : setTimeout + const clear = + typeof cancelIdleCallback === 'function' ? cancelIdleCallback : clearTimeout + + let id + + return function throttled() { + if (id) { + clear(id) + } + id = queue(func) + } +} + export { getData, getSanitizedData, @@ -197,4 +215,5 @@ export { deepMerge, unifiedToNative, measureScrollbar, + throttleIdleTask, }