Событие выгрузки окна реакции не срабатывает

Мне нужно использовать navigator.sendBeacon() при выгрузке окна, чтобы мой сервер знал, что клиент закрыл свое окно. Я искал везде, и это просто не работает для меня.

Для справки: решение в эта почта тоже не сработало.

У меня есть компонент приложения, который охватывает весь мой проект. Я пытаюсь установить событие выгрузки для его componentDidMount() метода жизненного цикла, и оно просто не срабатывает.

componentDidMount() {
  window.addEventListener("beforeunload", this.unload);
}

componentWillUnmount() {
  window.addEventListener("beforeunload", this.unload);
}

unload(e) {
  e.preventDefault();
  e.returnValue = 'test';
  navigator.sendBeacon(`http://localhost:8080/window-closed/${this.props.username}`);
  return 'test';
}

Я ожидаю, что сервер получит вызов AJAX, а окно предложит пользователю «тестировать» перед закрытием окна. Что на самом деле происходит, так это то, что окно просто закрывается, как обычно.

ПРИМЕЧАНИЕ: утверждения return 'test' и e.returnValue = '' предназначены исключительно для тестирования. Меня интересует только запрос AJAX.

Любая помощь приветствуется.

Не могли бы вы предоставить коды и ящик?

Jibin Joseph 28.03.2019 18:39

Попробуйте заменить unload(e) { на unload = (e) => {

Gabriele Petrioli 28.03.2019 19:09

К сожалению, это не сработало :/ @GabrielePetrioli

Sagi Rika 28.03.2019 19:18
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
3
10 315
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я не уверен, почему beforeunload не работает, но в качестве обходного пути вы можете рассмотреть возможность использования события hashchange.

componentDidMount() {
    window.addEventListener("hashchange", this.doSomething, false);
}

componentWillUnmount() {
    window.removeEventListener("hashchange", this.doSomething, false);
}

Вы пытались объявить функцию загрузки как функцию толстой стрелки? Также объявите его перед componentDidMount. (для лучшей читаемости) перед передачей в качестве ссылки.

Также вы пытались подключить прослушиватель в конструкторе? И сделайте surw для привязки вашей функции в конструкторе. Для справки

Также уничтожьте прослушиватель в componentWillUnmount вместо его добавления. (бесполезно) использовать ссылку на слушателя, чтобы уничтожить. Который вы создадите в конструкторе.

Удачи

Я не уверен, как вы имеете в виду, что я должен объявить это в конструкторе. Не могли бы вы показать мне какой-нибудь пример?

Sagi Rika 28.03.2019 19:19

Constructor (){ this.unload = this.unload.bind(this) И объявить выгрузку с помощью функции стрелки

mani9418 28.03.2019 19:39

Также не рекомендуется добавлять прослушиватели событий в реакцию, но пока вы можете использовать описанный выше подход, чтобы все исправить (y)

mani9418 28.03.2019 19:40
Ответ принят как подходящий

Вы должны привязать это к методу выгрузки или преобразовать его в функцию стрелки.

Запойный способ

constructor() {
    super();
    this.state = {
      //stuff
    };
    this.unload.bind(this);
  }

  componentDidMount() {
  window.addEventListener("beforeunload", this.unload);
}

componentWillUnmount() {
  window.removeEventListener("beforeunload", this.unload);
}

unload(e) {
  navigator.sendBeacon(`http://localhost:8080/window-closed/${this.props.username}`);
}

Стрелка работает так:

  constructor() {
    super();
    this.state = {
      //stuff
    };
  }

  componentDidMount() {
  window.addEventListener("beforeunload", this.unload);
  }

  componentWillUnmount() {
    window.removeEventListener("beforeunload", this.unload);
  }

  unload = (e) => {
    navigator.sendBeacon(`http://localhost:8080/window-closed/${this.props.username}`);
  }

Не забудьте удалить прослушиватель событий на componentWillUnmount (сейчас вы добавляете его снова).

Спасибо, воспользовался функциями стрелок, и он внезапно начал работать как шарм.

Sagi Rika 31.03.2019 09:55

что, если у нас есть подсказка. Например, «Внесенные вами изменения могут быть не сохранены». даже пользователь нажимает кнопку отмены, вызывая «перед выгрузкой» оконную функцию!

Sachin Kumar 28.12.2021 15:53

Вы можете использовать navigator.sendBeacon.

const UnloadBeacon = ({
  url,
  payload = () => {},
  children
}) => {
  const eventHandler = () => navigator.sendBeacon(url, payload())

  useEffect(() => {
    window.addEventListener('unload', eventHandler, true)
    return () => {
      window.removeEventListener('unload', eventHandler, true)
    }
  }, [])

  return children
}

полный пример здесь: https://gist.github.com/tmarshall/b5433a2c2acd5dbfc592bbc4dd4c519c

Если вы используете функциональный компонент, вы можете попробовать следующее:

 useEffect(() => {
    window.addEventListener("beforeunload", handleUnload);
    return () => {
      window.removeEventListener("beforeunload", handleUnload);
    };
  }, []);

  const handleUnload = (e) => {
    const message = "o/";
    (e || window.event).returnValue = message; //Gecko + IE
    return message;
  };


Эй, у меня сейчас похожая проблема, не могли бы вы проверить это? stackoverflow.com/questions/67498997/…

AdamSulc 12.05.2021 11:25

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