React 用于实时显示日志文件(Flask 后端)

React for displaying the log file in real-time (Flask backend)

我有一个工作代码(Flask + plain JS),它实时显示不断增长的日志文件。 我在将它转换为 ReactJS 时遇到问题。

app.py(Flask,工作代码,没问题)

@app.route('/stream')
def stream():
    def generate():
        fname="/Users/xxx/tmp/log.txt"
        with open(fname) as f:
            while True:
                yield f.read()
                sleep(1)
    return 
    app.response_class(generate(), mimetype='text/plain')

app.run()

index.html(纯 JS,没问题)

<pre id="output"></pre>
<script>
    var output = document.getElementById('output');
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '');
    xhr.send();

    setInterval(function() {
        output.textContent = xhr.responseText;
    }, 1000);
</script>

下面是我尝试将其转换为 React。

我在 MyPage.jsx 上放置了按钮 "Show Real Time Log"。 当用户单击此按钮时,模态对话框应弹出并显示日志。

文件:MyPage.jsx

import Modal from 'react-bootstrap/Modal'
import { Button } from 'react-bootstrap'

const showLog = (e) => {
    render(<ModalLog />,  document.getElementById('output'));
}

const MyPage = () => {
  return (
    <div>
          <div id="output"></div>
          <button type="button" onClick={showLog}>Show Real Time Log</button>
</div
}

function ModalLog() {
  const [show, setShow] = useState(true);

  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  return (
    <>
      <Modal show={show} onHide={handleClose}>
        <Modal.Header closeButton>
          <Modal.Title>Real Time Log</Modal.Title>
        </Modal.Header>
        <Modal.Body> Log file live update goes here </Modal.Body>
        <Modal.Footer>
          <Button variant="primary" onClick={handleClose}>
            Close
          </Button>
        </Modal.Footer>
      </Modal>
    </>
  );
}

问题:

  1. 将我index.html中的JS代码放到MyPage.jsx哪里?

  2. 当我按下按钮 "Show Real Time Log" 时,模态框只显示第一次,关闭后就再也没有显示过。我明白这是什么原因,因为 handleClose() 被调用了,但如何解决它?

(1) MyPage.jsx 我的 index.html 中的 JS 代码放在哪里?

简单的回答是你不知道。它直接操纵 DOM,这是一个严重的反模式。您可以将其转换为 useEffect 挂钩以获取最新的日志数据并将其保存到组件状态以进行渲染。

const [logs, setLogs] = useState('');
useEffect(() => {
  // asynchronous function to fetch logs
  const fetchLogs = async () => {
    try {
      const logResponse = await /* logic to fetch log */
      setLogs(logResponse);
    } catch {
      // just don't update state, or set an error message in state,
      // basically anything you want to do to handle errors
    }
  }

  // setup interval to fetch logs
  const intervalTimer = setInterval(fetchLogs, 1000);

  // function to clean up effect when component unmounts
  return () => clearInterval(intervalTimer);
}, []); // empty dependency array to run when mounted

(2) 当我按下按钮 "Show Real Time Log" 时,Modal 仅显示第一次,关闭后它再也不会显示。我明白这是什么原因,因为 handleClose() 被调用了,但如何解决它?

您显示模态的初始状态是 true。如果模态是否打开(而不是模态),我会稍微重构逻辑以使 MyPage 保持状态。将 showhandleClose 作为属性传递给 ModalLog。无需将模态渲染到另一个 DOM 元素中,我相信 react-bootstrap 将为您创建一个门户。您可以简单地将其渲染到您的组件中。

const MyPage = () => {
  const [show, setShow] = useState(false);

  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  return (
    <div>
      <div id="output"></div>
      <button type="button" onClick={handleShow}>Show Real Time Log</button>
      <ModalLog show={show} onHide={handleClose} />
    </div>
  );
}

function ModalLog({ show, onHide }) {
  return (
    <>
      <Modal show={show} onHide={onHide}>
        <Modal.Header closeButton>
          <Modal.Title>Real Time Log</Modal.Title>
        </Modal.Header>
        <Modal.Body> Log file live update goes here </Modal.Body>
        <Modal.Footer>
          <Button variant="primary" onClick={handleClose}>
            Close
          </Button>
        </Modal.Footer>
      </Modal>
    </>
  );
}

建议:放置日志状态和逻辑以获取和显示日志在模态中,因为看起来您只关心显示当模态打开时获取它们,当模态关闭时在后台获取它们毫无意义。