Tìm kiếm trang web

reactjs - Bắt lỗi JavaScript bên trong iframe được định nghĩa bằng thuộc tính srcDoc


Tôi đang tạo một component React hiển thị HTML/JavaScript tùy ý bên trong một iframe được đặt bằng thuộc tính srcDoc. Tuy nhiên, iframe có thể chứa các script có thể gặp lỗi và tôi muốn hiển thị một thông báo lỗi thay vì iframe trong trường hợp đó. Tuy nhiên, việc kích hoạt lỗi dường như rất không nhất quán, tôi đoán là do vấn đề về thời gian. Làm thế nào để tôi đảm bảo trình xử lý lỗi được kích hoạt?

const RenderHtml = ({ htmlBlock }: { htmlBlock: HtmlBlock }) => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [hasError, setHasError] = useState<boolean>(false);

  useEffect(() => {
    if (!iframeRef.current) return;
    const iframe = iframeRef.current;

    if (iframe.contentWindow) {
      iframe.contentWindow!.addEventListener("error", onIframeError);
    }

    return () => {
      if (iframe.contentWindow) {
        iframe.contentWindow!.removeEventListener("error", onIframeError);
      }
    }
  }, [htmlBlock.html]);

  const onIframeError = (event: ErrorEvent) => {
    event.preventDefault();
    setHasError(true);
  };

  return !hasError ? (
    <iframe
      ref={iframeRef}
      srcDoc={htmlBlock.html}
      style={{
        border: "none",
        width: "100%",
      }}
    ></iframe>
  ) : (
    <Alert color="danger">There was an error loading the HTML content</Alert>
  );
};

Câu trả lời #1

  1. Di chuyển logic xử lý lỗi vào bên trong hook useEffect để đảm bảo nó được thiết lập đúng khi iframe sẵn sàng.
  2. Sử dụng sự kiện load thay vì sự kiện error để xử lý các lỗi tiềm ẩn trong nội dung của iframe.

Ví dụ :

import React, { useEffect, useRef, useState } from "react";

const RenderHtml = ({ htmlBlock }: { htmlBlock: HtmlBlock }) => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [hasError, setHasError] = useState<boolean>(false);

  useEffect(() => {
    if (!iframeRef.current) return;

    const iframe = iframeRef.current;

    const handleLoad = () => {
      // Check if the iframe's contentDocument is accessible
      // and whether it contains any error messages
      if (iframe.contentDocument?.querySelector("body script[src^='chrome-error://']")) {
        setHasError(true);
      }
    };

    iframe.addEventListener("load", handleLoad);

    return () => {
      iframe.removeEventListener("load", handleLoad);
    };
  }, [htmlBlock.html]);

  return !hasError ? (
    <iframe
      ref={iframeRef}
      srcDoc={htmlBlock.html}
      style={{
        border: "none",
        width: "100%",
      }}
    ></iframe>
  ) : (
    <Alert color="danger">There was an error loading the HTML content</Alert>
  );
};

Bài viết liên quan