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>
</>
);
}
问题:
将我index.html中的JS代码放到MyPage.jsx哪里?
当我按下按钮 "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
保持状态。将 show
和 handleClose
作为属性传递给 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>
</>
);
}
建议:放置日志状态和逻辑以获取和显示日志在模态中,因为看起来您只关心显示当模态打开时获取它们,当模态关闭时在后台获取它们毫无意义。
我有一个工作代码(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>
</>
);
}
问题:
将我index.html中的JS代码放到MyPage.jsx哪里?
当我按下按钮 "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
保持状态。将 show
和 handleClose
作为属性传递给 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>
</>
);
}
建议:放置日志状态和逻辑以获取和显示日志在模态中,因为看起来您只关心显示当模态打开时获取它们,当模态关闭时在后台获取它们毫无意义。