Реагирование на отображение файла журнала в режиме реального времени (Flask backend) - PullRequest
0 голосов
/ 22 марта 2020

У меня есть рабочий код (Flask + обычный 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 , без проблем)

<code><pre id="output">
var output = document.getElementById ('output'); var xhr = new XMLHttpRequest (); xhr.open ('GET', ''); xhr.send (); setInterval (function () {output.textContent = xhr.responseText;}, 1000);

Ниже приведена моя попытка преобразовать его в React.

В MyPage.jsx я поставил кнопку «Показать журнал в реальном времени». Когда пользователь нажимает эту кнопку, должно появиться модальное диалоговое окно и отобразить журнал.

Файл: 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. Где поместить в MyPage.jsx код JS, который сейчас находится в моем индексе. html?

  2. Когда я нажимаю кнопку «Показать журнал в реальном времени», отображается модал только 1-й раз, после закрытия он больше не отображается Я понимаю, что это потому, что handleClose () был вызван, но как это исправить?

1 Ответ

1 голос
/ 22 марта 2020

(1) Где поместить в MyPage.jsx код JS, который сейчас находится в моем индексе. html?

Простой ответ - нет. Он напрямую манипулирует 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) Когда я нажимаю кнопку «Показать реальное Time Log "Модал отображается только 1-й раз, после закрытия он больше никогда не отображается. Я понимаю, что это потому, что handleClose () был вызван, но как это исправить?

Вы установили модальное состояние для отображения true. Я бы немного переработал логи c, чтобы MyPage удерживал состояние, если модальное открыто или нет (вместо модального). Передайте show и handleClose в качестве реквизита на ModalLog. Не нужно рендерить модал в другой элемент DOM, я думаю, что реакция - 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>
    </>
  );
}

Предложение : поместите состояние журнала и logi c, чтобы получить и отобразить журналы в модальном Похоже, вы хотите отображать их только тогда, когда модальное окно открыто, и нет смысла извлекать их в фоновом режиме, пока модальное окно закрыто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...