Свойство ‘msHidden’ не существует для типа ‘Document’

#javascript #html #reactjs #typescript #interface

#javascript #HTML #reactjs #typescript #интерфейс

Вопрос:

Я получаю эту ошибку при использовании видимости вкладок. В котором ‘msHidden’ и ‘webkitHidden’ не существуют для типа ‘Document’

 const TabVisibilityComponent = () => {
let hidden = null;
let visibilityChange = '';
const [action, setAction] = useState('show');
if (typeof document.hidden !== 'undefined') {
  hidden = 'hidden';
  visibilityChange = 'visibilitychange';
} else if (typeof document.msHidden !== 'undefined') {
  hidden = 'msHidden';
  visibilityChange = 'msvisibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
  hidden = 'webkitHidden';
  visibilityChange = 'webkitvisibilitychange';
}

const handleVisibilityChange = () => {
  if (document.hidden) {
    setAction('hide');
  } else {
    setAction('show');
  }
};


useEffect(() => {
  document.addEventListener('visibilitychange', handleVisibilityChange, false);
  window.addEventListener(
    'focus',
    function() {
      setAction('show');
    },
    false,
  );
  window.addEventListener('blur', function() {
    setAction('hide');
  }, false);
}, [visibilityChange]);
return <p></p>;
};

export default TabVisibilityComponent;
 

Я попытался добавить ‘только для чтения msHidden: boolean’ в интерфейс документа в файле ‘lib.dom.d.ts’, потому что hidden работает нормально, и в этом файле он объявлен как логическое значение только для чтения, поэтому попробовал то же самое для msHidden и webkitHidden, но это не работает. Я видел, что этот код используется многими, но не знаю, в чем ошибка с моим. Был бы очень рад, если бы у кого-нибудь нашлось решение для этого!

Ответ №1:

Код взят прямо из документов MDN, так что вы правы в том, что сам код в порядке. Проблемы заключаются в:


  1. lib.dom Определения действительно включают свойства, зависящие от браузера.

Один из способов обойти это — передать документ в качестве аргумента функции, которая определяет эти свойства как необязательные.

 const hiddenPropName = (document: Document amp; {msHidden?: boolean; webkitHidden?: boolean}) => {
  if (typeof document.hidden !== "undefined" ) {
    return "hidden";
  } else if (typeof document.msHidden !== "undefined") {
    return "msHidden";
  } else if (typeof document.webkitHidden !== "undefined") {
    return "webkitHidden";
  }
  // not sure how to handle when none exist
}
 

Но что касается машинописного текста, document.hidden он всегда существует.

Похоже, что вряд ли есть какая-либо разница между номерами для поддержки с префиксом и без префикса в caniuse. Так что вы могли бы просто отказаться от msHidden and webkitHidden .


  1. Вы игнорируете hidden visibilityChange переменные и, которые вы устанавливаете.

Первый раздел кода в примере — это просто настройка переменных hidden и visibilityChange имен свойств, чтобы позже они могли получить доступ к правильным свойствам. В примере используется document[hidden] where hidden — переменная, но вы использовали document.hidden which, которая всегда получает свойство «hidden» и никогда «msHidden» или «webkitHidden».

Они также используют переменную для события в document.addEventListener .

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


  1. Вы неправильно адаптируете код к React.

Вы хотите убедиться, что ваш useEffect хук имеет правильные зависимости, и в идеале вам следует использовать функцию очистки в вашем useEffect , чтобы удалить прослушиватели событий при размонтировании.

Самое сложное здесь — убедиться, что вы не создаете устаревших замыканий, которые будут использовать устаревшие значения document при оценке. На самом деле я не уверен, не играя с этим, правильно ли это:

 const TabVisibilityComponent = () => {
  const [action, setAction] = useState("show");

  useEffect(() => {
    const hide = () => setAction("hide");

    const show = () => setAction("show");

    const handleVisibilityChange = () => {
      document.hidden ? hide() : show();
    };

    document.addEventListener(
      "visibilitychange",
      handleVisibilityChange,
      false
    );
    window.addEventListener("focus", show, false);
    window.addEventListener("blur", hide, false);

    return () => {
      document.removeEventListener("visibilitychange", handleVisibilityChange);
      window.removeEventListener("focus", show);
      window.removeEventListener("blur", hide);
    };
  }, [setAction]);

  return <p></p>;
};