Axios все еще возвращает данные после использования AbortController в React

В общем, я пытаюсь понять, что не так с моим кодом, связанным с отменой запроса на публикацию axios. У меня есть форма, через которую пользователь может сделать запрос на поиск фильмов в openai. Пока поиск продолжается, я предоставляю пользователю кнопку отмены, позволяющую прервать поиск и ввести новый поисковый запрос. Если во время тестирования я прерву запрос, я все равно получу данные, и они все равно будут обрабатываться, как если бы запрос не был отменен.

Это происходит в компоненте React, который я посвятил обработке запроса openai. Согласно моему package.json, я использую Axios 9.5.0. Первое, что я делаю внутри компонента, — устанавливаю состояние, а затем:

  const controller = new AbortController();

Вот обработчик, когда пользователь отправляет поиск:

const handleSubmit = async () => {
    (set some states to set up correct user interface)

    try {
      const searchResults = await axios.post(
        "/api/movies/ai-search",
        {
          userRequest: request,
        },
        { signal: controller.signal }
      );
      const jsonResults = JSON.parse(searchResults.data);
      
      (do stuff with the returned data)
      
    } catch (err) {
      if (axios.isCancel(err)) {
        console.info("Request cancelled");
      } else {
        console.info(err);
      }
      
      (set some more states to reflect error message)

      );
    }
  };

А вот обработчик, когда пользователь нажимает кнопку, чтобы отменить текущий поиск:

  const handleSearchCancel = (e: React.MouseEvent<HTMLButtonElement>) => {
    // handler for when user cancels search
    console.info("Cancelling the search") // confirm I made it to the handler
    controller.abort();
    
    (set a couple of states to update the UI)
  };

Одна из проблем, которая, как мне показалось, может заключаться в том, что все настройки состояния: большинство из них создаются из родительского компонента. Может ли это быть причиной проблемы? В любом случае, если я отправлю поиск, а затем отменю его, я получу журнал консоли о том, что нахожусь в правильном обработчике. Но если я подожду еще несколько минут, результаты поиска появятся и будут обработаны так, как будто запрос не был отменен.

Обновлено:

По предложению Дата я переключился на настройку useRef:

  const abortControllerRef = useRef<AbortController>(new AbortController());

Это сработало для первого поиска... но все последующие поиски немедленно отменяются без участия пользователя. При исследовании этого вопроса мне кажется, что мне нужно создать новый AbortController для каждого запроса. НО, поскольку я использую useRef, я не могу сделать это в обработчике кликов. Попробую сделать это в кастомном хуке.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
498
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Можете ли вы еще раз проверить версию вашего Axios? Axios 9.5.0 не существует.

Да, меня это тоже смутило. В моем package.json есть axios: "^1.6.7", но когда я делаю npm -v axis в командной строке, я получаю обратно 9.5.0.

lkalliance 28.02.2024 21:01

Гость, вы «(установите несколько состояний для настройки правильного пользовательского интерфейса)» сделали контроллер в запросе и в handleCancel разными. Так что можешь попробовать const abortControllerRef = useRef<AbortController>(new AbortController()); или const abortControllerRef = useMemo(()=> {return new AbortController()},[])

Dat Huynh 28.02.2024 21:30

Дат, чтобы убедиться, что я правильно понимаю, useRef сохраняет свое значение, если измененное состояние приводит к повторному рендерингу, поэтому, помещая новый AbortController в ссылку, он не инициализируется повторно. Я правильно это понимаю?

lkalliance 28.02.2024 21:49

Правильно, основная цель — сохранить одинаковые оба контроллера.

Dat Huynh 28.02.2024 21:57

Отчасти это сработало! Когда я отменяю запрос (abortControllerRef.current.abort();), он отменяется, я получаю соответствующую запись в журнале «запрос отменен». НО... если я отправлю еще один поиск, он будет немедленно отменен без вмешательства пользователя.

lkalliance 28.02.2024 22:03

И по поводу вашего замешательства по поводу версии аксиоса. Команда npm -v axis возвращает версию npm. Вы можете попробовать другое имя пакета, оно всегда возвращает 9.5.0. Поэтому, если вы хотите проверить версию пакета, вам следует использовать sudo npm view axios version или npm view axios version.

Dat Huynh 28.02.2024 22:04

Да, это верно. Потому что атрибут aborted теперь верен. Вы можете увидеть изображение, которое я добавил в свой ответ, взятое из пакета axios. Таким образом, он может решить проблему, объявив, что ссылка равна нулю. После этого, когда вы отправили запрос, сделайте так, чтобы он стал abortControllerRef = useRef<AbortController>(new AbortController());. Наконец, когда вы отмените запрос, сделайте его снова равным нулю.

Dat Huynh 28.02.2024 22:11

Давайте продолжим обсуждение в чате.

lkalliance 28.02.2024 22:24

Хорошо, с помощью Дата мы это выяснили.

  1. useRef выполнил свою работу правильно: я мог бы использовать его для ссылки на AbortController:

const abortRef = useRef<AbortController>(new AbortController())

и я мог бы сослаться на него в функции cancelSearchHandler. НО... как только я это сделал, поиск НАВСЕГДА прерывается. Все последующие поиски без обновления были автоматически отменены. Так...

  1. Повторно создайте новый экземпляр AbortController при отправке поиска. ЗА ИСКЛЮЧЕНИЕМ я не смог сделать это внутри обработчика отправки. Невозможно использовать хуки React внутри обработчиков, они должны находиться на верхнем уровне компонента. Итак, «мы» наконец получили ответ...

  2. Забудьте о хуках React, используйте стандартный JavaScript для создания экземпляра контроллера, но делайте это ВНЕ компонента (гениально, Дат!). Тот же модуль, только за пределами компонента. Так:

let controller: AbortController;

Это было вне компонента, что делало его одинаково доступным как для обработчика отправки, так и для обработчика отмены. Затем используйте его как обычно.

Другие вопросы по теме