#reactjs #ajax #react-component
#reactjs #ajax #react-component
Вопрос:
Я использую React 16.13.0. У меня есть это окно поиска, в котором люди вводят и ожидают увидеть результаты по мере ввода…
return (
<div className="searchForm">
<input
type="text"
placeholder="Search"
value={this.state.searchTerm}
onChange={this.handleChange}
/>
Я использую приведенные ниже функции для обработки получения результатов по мере ввода текста людьми…
handleChange(event) {
const query = event.target.value;
if (!query) {
this.setState({ searchTerm: query, searchResults: [] });
} else {
this.setState({ searchTerm: query, loading: true }, () => {
this.doSearch(query);
});
}
}
doSearch = (query) => {
const searchUrl = "/coops/?contains=" encodeURIComponent(query);
fetch(searchUrl, {
method: "GET",
})
.then((response) => response.json())
.then((data) => {
if (query === this.state.searchTerm) {
this.setState({
searchResults: data,
loading: false,
});
}
});
};
Я пытаюсь сократить количество выполняемых / обрабатываемых сетевых вызовов. Если кто-то вводит строку типа «res» довольно быстрым способом, его, вероятно, не волнуют результаты для «r» или «re», поэтому мне было интересно, есть ли какой-нибудь способ, которым я могу отменить запрос, если в моей строке поиска введена новая буква? Или выполнять поиск только в том случае, если кто-то перестал печатать как минимум на 100 мс (не уверен, достаточно ли этого времени, но решил выбрать произвольное количество)?
Комментарии:
1. Смотрите JavaScripts ‘clearTimeout’ и ‘setTimeout’
2. Исследуйте «debounce».
Ответ №1:
То, что вам нужно, обычно называется debounce. Существует ряд библиотек, которые реализуют эту функциональность, включая. Lodash и подчеркивание. Например, в Lodash вы бы сделали следующее:
onChange={e => debouncedHandler(e, this.handleChange)}
и определил следующее вне компонента:
const debouncedHandler = _.debounced((e, handler) => handler(e), 100);
Объявление отмененной функции внутри самого компонента является распространенной ошибкой. Это не сработает, потому что react перезапускает этот код при каждом изменении и, следовательно, заново создает отмененную функцию, следовательно, отмена не произойдет. Поэтому важно определить отмененную функцию вне компонента.
Обновление: в коде, который у меня был ранее, была ошибка. Я думаю, теперь это исправлено. Я этого не тестировал.
Комментарии:
1. Привет, в «onChange={getDebouncedHandler(e, this.handleChange, 100)}», что такое «e»? Я получаю неопределенную ошибку, когда пытаюсь добавить это в мое событие onChange для моего текстового поля.
2. На самом деле была еще одна ошибка в том, как / когда я создавал отмененную функцию. Я думаю, что теперь это исправлено.
Ответ №2:
Вы можете отложить поиск с помощью setTimeout
. Просто сбрасывайте время ожидания всякий раз, когда перехватывается новый ввод. Если таймер истекает, перейдите и выполните запрос
handleChange = (e) => {
this.setState(
{
searchTerm: e.target.value
},
() => {
try {
clearInterval(window.xhrSearchTimer);
} catch (e) {
console.log(`no timeout initialized`);
}
window.xhrSearchTimer = window.setTimeout(() => {
this.doSearch(this.state.searchTerm);
}, 1000); // arbitrary value
}
);
};
doSearch = () => {
alert(`Now searching for ${this.state.searchTerm}`);
};
https://codesandbox.io/s/loving-sid-hb0nr?file=/src/App.js:139-622
Ответ №3:
Вы можете использовать какой-нибудь помощник, подобный этому, и передать вызывающую функцию в качестве первого аргумента callback
.
function getDoneTyping (callback, wait = 300) {
let timer
const keyDownHandler = event => {
if (event.key === 'Enter') {
callback()
}
clearTimeout(timer)
}
const keyUpHandler = event => {
clearTimeout(timer)
timer = setTimeout(callback, wait)
}
return { keyDownHandler, keyUpHandler }
}