Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
Collapse
exlends
Категории
  1. Home
  2. Categories
  3. Фронтенд
  4. React
  5. Оптимизация React js приложений. Использование функции debounde()

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

Scheduled Pinned Locked Moved React
5 Posts 3 Posters 142 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JspiJ Offline
    JspiJ Offline
    Jspi
    js
    wrote on last edited by
    #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 Reply Last reply
    👍
    3
    • kirilljsxK Offline
      kirilljsxK Offline
      kirilljsx
      js
      wrote on last edited by kirilljsx
      #2

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

      JspiJ ManulM 3 Replies Last reply
      2
      • kirilljsxK kirilljsx

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

        JspiJ Offline
        JspiJ Offline
        Jspi
        js
        wrote on last edited by
        #3

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

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

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

        1 Reply Last reply
        0
        • kirilljsxK kirilljsx

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

          JspiJ Offline
          JspiJ Offline
          Jspi
          js
          wrote on last edited by
          #4

          @kirilljs

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

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

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

          1 Reply Last reply
          0
          • kirilljsxK kirilljsx

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

            ManulM Offline
            ManulM Offline
            Manul
            wrote on last edited by Manul
            #5

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

            1 Reply Last reply
            🤔
            1

            Категории

            • Главная
            • Новости
            • Фронтенд
            • Бекенд
            • Языки программирования

            Контакты

            • Сотрудничество
            • info@exlends.com
            • Наш чат
            • Наш ТГ канал

            © 2024 - 2025 ExLends, Inc. Все права защищены.

            Политика конфиденциальности
            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups