Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting console logs from iframe error #67

Closed
Foscat opened this issue Nov 14, 2020 · 1 comment
Closed

Getting console logs from iframe error #67

Foscat opened this issue Nov 14, 2020 · 1 comment

Comments

@Foscat
Copy link

Foscat commented Nov 14, 2020

I am trying to get the logs from an iframe and have run into several major issues. I have not been able to find a example of getting logs from one anywhere, so I found a way to get them but I am not sure it is the proper way. That leads to my core issue is getting the Hook() to work correctly. It will either never run or it will run in a infinite loop. Here is the component I am making to show the iframe and the logs below. I have a operation in the setLogs hook to prevent the endless empty data arrays from being added to the state.

Here is a video I made of the error and how it happens. https://drive.google.com/file/d/1qtrsCLr8RTC1TirnpXKuGkDkwVpfTRL4/view

My React Component:

`
import React, { useState, useEffect } from "react";
import { Hook, Console, Decode, Unhook } from "console-feed";
import SplitPane from "components/SplitPane/SplitPane";

const WebViewer = ({ webTemplate }) => {
const [contentRef, setContentRef] = useState(null);

const useFrameObject = () => {
const [logs, setLogs] = useState([]);
const frameData = contentRef?.contentWindow?.console;

useEffect(() => {
  function grabConsoleData() {
    console.log("grab console data", frameData);
    if (frameData) {
      Hook(frameData, (log) =>
        setLogs((curLogs) =>
          log[0].data.length ? [...curLogs, Decode(log)] : [...curLogs]
        )
      );
      console.log("hook ran now unhook");
      return () => Unhook(contentRef);
    }
  }

  // For some reason the loop will not run unless this function is called but is always a undefined value so I have it called as a unused varible
  // eslint-disable-next-line
  let foundLog = frameData?.feed?.pointers.log();
  console.log("add"); // To keep track of when event listener is added
  document
    .getElementById("webPreviewFrame")
    .addEventListener("load", grabConsoleData);

  grabConsoleData();

  return () => {
    console.log("remove");// To keep track of when the event listener is removed
    document
      .getElementById("webPreviewFrame")
      .removeEventListener("load", grabConsoleData);
  };
}, [frameData]); // If I have a dependency array it never catches logs, without it logs appear in logs state but endless loop
console.log("return logs", logs);
return logs;

};

return (

<iframe
id="webPreviewFrame"
title="Web Preview"
className="editor_console_panel"
srcDoc={${webTemplate}}
referrerPolicy="origin"
width="100%"
ref={setContentRef}
/>
<div
style={{ backgroundColor: "#242424", height: "100%", width: "100%" }}
>



);
};

export default WebViewer;
`

SrcDoc string being fed into the iframe:

<!DOCTYPE html><html><body><h1>Hey Buddy</h1><script>console.log("hey",2);console.log("Bro")<script/></body></html

@Foscat
Copy link
Author

Foscat commented Nov 20, 2020

I figured it out, I took the Hook out of a use effect and placed it inside the onLoad function of the iframe. Then on my website template I put the code into I wrap the incoming JavaScript in a settimout then execute the code and it works for the runtime logs any user click logs.

webTemplateProp

let template = `<!DOCTYPE html>
		<html lang="en">
		<head>
		  <meta charset="UTF-8">
		  <meta name="viewport" content="width=device-width, initial-scale=1.0">
		  <style>${this.state.cssEditorContent}</style>
		</head>
		<body id="body">
		${this.state.htmlEditorContent}
		</body>
    <script>
    setTimeout(() => {
      ${this.state.jsEditorContent}
    }, 250);
		</script>
		</html>`;

React Code

import React, { Component, createRef } from "react";
import { Hook, Console, Decode } from "console-feed";
import SplitPane from "components/SplitPane/SplitPane";

class Ughh extends Component {
  constructor(props) {
    super(props);
    this.state = {
      logs: [],
      contentRef: createRef(),
    };
  }


  render() {
    return (
      <SplitPane orientation="horizontal">
        <iframe
          id="webPreviewFrame"
          title="Web Preview"
          className="editor_console_panel"
          srcDoc={`${this.props.webTemplate}`}
          referrerPolicy="origin"
          width="100%"
          ref={this.state.contentRef}
          onLoad={() => {
            Hook(this.state.contentRef.current.contentWindow.console, log => {
              this.setState(({ logs }) => ({ logs: [...logs, Decode(log)] }))
            });
          }}
        />
        <div
          style={{ backgroundColor: "#242424", height: "100%", width: "100%" }}
        >
          <Console logs={this.state.logs} variant="dark" />
        </div>
      </SplitPane>
    );
  }
}

export default Ughh;

I hope this helps anyone who runs into this issue as I did.

@Foscat Foscat closed this as completed Nov 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant