【发布时间】:2020-08-25 08:52:09
【问题描述】:
我有一个页面显示每 180 秒(3 分钟)从 API 检索的一些数据。当页面加载时,我有一个初始的 useEffect 挂钩来调用 retrieveData() 函数。然后,使用下面的代码和一个名为 elapsed 的状态变量,我开始了 180 秒的间隔。每隔一秒,我会更新一个从 3 分钟开始倒计时的进度条,并显示剩余时间。这使用经过的状态变量。
这是开始间隔的钩子:
useEffect(() => {
const interval = setInterval(() => {
if (elapsed < dataUpdateInterval) {
setElapsed(elapsed + 1);
} else {
setElapsed(0);
retrieveData();
}
}, 1000);
return () => clearInterval(interval);
}, [elapsed]);
我的问题是,为什么页面上的其余组件会在间隔的每个刻度上重新呈现?我认为由于我只更新经过的状态变量,因此只有那些组件会更新使用该状态变量的组件。我的表格显示数据(存储在另一个状态变量中)应该每 3 分钟更新一次。
如果这还不够,很乐意提供其他信息。
更新 1: 在开发工具中,我得到重新渲染的原因是“Hooks changed”
更新 2: 下面是使用此计时器的代码的 sn-p。 StatusList 和 StatusListItem 组件使用 React.memo 并且是功能组件。状态列表是一个 IonList,而 StatusListItem 是一个顶级的 IonItem(来自 Ionic)
import React, { useEffect, useState } from "react";
import { Layout } from "antd";
import StatusListItemNumbered from "./StatusListItemNumbered";
import { Container, Row, Col } from "react-bootstrap";
import StatusList from "./StatusList";
import { Progress } from "antd";
import moment from "moment";
const Content = React.memo(() => {
const dataUpdateInterval = 180;
const [elapsed, setElapsed] = useState(0);
const [data, setData] = useState();
const timeLeft = (interval, elapsed) => {
let time = moment.duration(interval - elapsed, "seconds");
return moment.utc(time.asMilliseconds()).format("mm:ss");
};
const retrieveData = () => {
console.log("Retrieving data");
SomeApi.getData().then(items => {
setData(items);
})
};
//The effect hook responsible for the timer
useEffect(() => {
setTimeout(() => {
if (elapsed < dataUpdateInterval) {
setElapsed(elapsed + 1);
} else {
setElapsed(0);
retrieveData();
}
}, 1000);
}, [elapsed]);
//Retrieve data the very first time the component loads.
useEffect(() => {
retrieveData();
}, []);
//Component styling
return (
<Layout.Content style={{ padding: "20px 20px" }}>
<div className={css(styles.siteLayoutContent)}>
<Container className={css(styles.mainContainer)}>
<Row className={css(styles.progressRow)}>
<Col>
<Progress
style={{ marginLeft: "17px", width: "99%" }}
strokeColor={{
"0%": "#108ee9",
"100%": "#87d068",
}}
percent={(100 / dataUpdateInterval) * elapsed}
format={() => `${timeLeft(dataUpdateInterval, elapsed)}`}
/>
</Col>
</Row>
<Row>
<Col sm={6}>
<StatusList listName="Data">
{data &&
data.map((item, index) => {
return (
<StatusListItemNumbered
key={index}
value={item.count}
label={item.company}
/>
);
})}
</StatusList>
</Col>
</Row>
</Container>
</div>
</Layout.Content>
);
});
export default Content;
【问题讨论】:
标签: javascript reactjs