У меня есть браузерное приложение с архитектурой React-Redux. В приложении происходит много событий (например, тайм-ауты, входящие сообщения через веб-сокет, сообщения веб-работников, ответы XHR и т.д.). Каждое событие генерирует действие Redux, которое изменяет хранилище Redux, которое вызывает рендеринг React.
Проблема в том, что события происходят так часто, что React не имеет достаточно времени для визуализации пользовательского интерфейса (например, событие происходит каждые 5 мс (или чаще), а React требуется 10 мс для визуализации пользовательского интерфейса). Это приводит к тому, что вся страница перестает отвечать на запросы, потому что процесс рендеринга не останавливается (у него всегда есть что-то для рендеринга), и у браузера нет времени рисовать DOM или обрабатывать событие DOM.
Каковы подходы или готовые решения для решения этой проблемы, учитывая, что я не могу уменьшить ни частоту событий, ни время рендеринга React?
Когда вы обновляете состояние из сообщения веб-сокета, запишите время и делайте еще одно обновление, только если с тех пор прошло определенное время.
В этом примере состояние обновляется, только если прошло 1000 мс с момента последнего обновления:
client.onUpdate(data => {
if (!this.lastUpdate ||
new Date().getTime() - this.lastUpdate.getTime() > 1000) {
this.setState({ data });
this.lastUpdate = new Date();
}
})
Вы можете просто отменить ваш обработчик.
Функция debounce означает, что она может быть вызвана только один раз за X период времени.
Для примера я не буду реализовывать детали отмены функции, а использую lodash
.
// function that handles the server update.
const serverUpdateHandler = (dispatch) => {
dispatch({
type: SERVER_UPDATE
})
}
// create a new function that is debounced. aka - will invoke after 250 milliseconds after the lace invokation
const debouncedHandler = _.debounce(serverUpdateHandler,250);
// pass socket.io the debounced function
socket.on('server-update',debouncedHandler)
memoization
? reactjs.org/blog/2018/06/07/...