Перейти к содержанию
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
Логотип бренда
Категории
  1. Главная
  2. Категории
  3. Фронтенд
  4. React
  5. Оптимизация React js приложений. Использование функции debounde()

Оптимизация React js приложений. Использование функции debounde()

Запланировано Прикреплена Закрыта Перенесена React
5 Сообщения 3 Постеры 97 Просмотры 1 Watching
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • JspiJ Не в сети
    JspiJ Не в сети
    Jspi
    js
    написал в отредактировано
    #1

    Допустим мы имеем очень абстрактный компонент, который имеет поле ввода текста, кнопку отправки этого текста на сервер, и сообщение о состоянии отправки данных на сервер

    Пример кода

    
    // функция иммитации запроса на сервер
    function fakeFetch(val: string) {
      return new Promise<string>(function (resolve) {
        setTimeout(function () {
          resolve(`Сервер получил сообщение: ${val}`);
        }, 1000);
      });
    }
    
    //  самый простой пример компонента
    function App() {
      const [val, setVal] = useState('');
      const [response, setResponse] = useState('');
    
      const inputHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
        setVal(e.target.value);
        setResponse('');
      };
    
      const submitHandler = async () => {
        setVal('');
        setResponse('отправка ...');
        const resp = await fakeFetch(val);
        setResponse(resp);
      };
    
      return (
        <>
          <input type="text" value={val} onInput={inputHandler} />
          <button onClick={submitHandler}>Отправить</button>
          <p>{response}</p>
        </>
      );
    }
    

    Теперь перед нами встала задача заменить поведение: отправлять данные не по кнопке, а автоматически. Однако мы не может просто так повесить функцию в обработчик inputHandler(), мало того что он будет неоправданно часто отправлять запросы на сервер, так еще и будет сбивать значение val. Но если мы добавить функцию debounce(), то она решит эти вопросы.

    Функция debounce()

    debounce() - это функция-обертка, которая ограничивает число выполнений переданной в нее функции, некоторым промежутком времени. Если точнее, то, пока промежуток времени не прошел, то зарегистрированная функция не будет исполнятся, а пока она не исполнилась, новый вызов функции будет замещать старый, исключая повторное выполнение.

    пример:

    function debounce(func, delay: number) {
      let timeoutId: number;
    
      return (...args) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func(...args), delay);
      };
    }
    

    Как правильно использовать в React компоненте

    function App() {
      const [val, setVal] = useState('');
      const [response, setResponse] = useState('');
    
      const inputHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
        setVal(e.target.value);
        setResponse('');
    
        debounceHandler();
      };
    
      const submitHandler = useCallback(async () => {
        setResponse('отправка ...');
        const resp = await fakeFetch(val);
        setVal('');
        setResponse(resp);
      }, []);
    
      const debounceHandler = useMemo(() => {
        return debounce(submitHandler, 800);
      }, [submitHandler]);
    
      return (
        <>
          <input type="text" value={val} onInput={inputHandler} />
          {/* <button onClick={submitHandler}>Отправить</button> */}
          <p>{response}</p>
        </>
      );
    }
    

    При изменении стейта функциональный компонент вызывает свою функцию каждый раз, и без мемоизации мы бы получали каждый раз новый обработчик debounceHandler() и submitHandler(). Но для того чтобы все работало нам необходимо передать одну функцию в debounce один раз!

    Поэтому мемоизируем submitHandler() через useCallback (линтер обычно потребует указать submitHandler как зависимость debounceHandler) и саму функцию debounceHandler() в useMemo, (т.к debounce() возвращает функцию)

    1 ответ Последний ответ
    👍
    3
    • kirilljsK Не в сети
      kirilljsK Не в сети
      kirilljs
      js
      написал в отредактировано kirilljs
      #2

      Простыми словами, мы колбэчим submitHandler через debounceHandler то как оно должно быть по спецификации JS ? И почему onInput, а не onChange ?

      JspiJ ManulM 3 ответов Последний ответ
      2
      • kirilljsK kirilljs

        Простыми словами, мы колбэчим submitHandler через debounceHandler то как оно должно быть по спецификации JS ? И почему onInput, а не onChange ?

        JspiJ Не в сети
        JspiJ Не в сети
        Jspi
        js
        написал в отредактировано
        #3

        Пользователь @kirilljs написал в Оптимизация React js приложений. Использование функции debounde():

        Простыми словами, мы колбэчим submitHandler через debounceHandler то как оно должно быть по спецификации JS

        не понял вопроса, напомню, чтчо тут не используется никаких форм, фактически все обработчики привязаны к onInput событию, функция debounce() - самописная

        1 ответ Последний ответ
        0
        • kirilljsK kirilljs

          Простыми словами, мы колбэчим submitHandler через debounceHandler то как оно должно быть по спецификации JS ? И почему onInput, а не onChange ?

          JspiJ Не в сети
          JspiJ Не в сети
          Jspi
          js
          написал в отредактировано
          #4

          @kirilljs

          Пользователь @kirilljs написал в Оптимизация React js приложений. Использование функции debounde():

          И почему onInput, а не onChange

          onInput отлавливает все изменения значения в <input />, даже такие как нажатие клавиш и вставку текста, поэтому он предпочтительнее в данном случае

          1 ответ Последний ответ
          0
          • kirilljsK kirilljs

            Простыми словами, мы колбэчим submitHandler через debounceHandler то как оно должно быть по спецификации JS ? И почему onInput, а не onChange ?

            ManulM Не в сети
            ManulM Не в сети
            Manul
            написал в отредактировано Manul
            #5

            @kirilljs Возможно магия реакта onInput и onChange делает идентичными, https://github.com/facebook/react/issues/3964
            Скорее всего можно использовать и то и то

            1 ответ Последний ответ
            🤔
            1

            • Войти

            • Нет учётной записи? Зарегистрироваться

            • Войдите или зарегистрируйтесь для поиска.
            • Первое сообщение
              Последнее сообщение
            0
            • Категории
            • Последние
            • Метки
            • Популярные
            • Пользователи
            • Группы