【发布时间】:2019-06-19 06:21:10
【问题描述】:
我正在使用 alpha 版本的 react 支持钩子,并且想验证我在间隔后更新组件中文本的方法而不在道具更改时渲染组件的次数超过所需次数.
编辑:为了清楚起见 - 这个组件在
formatTimeString函数 (docs here) 中调用moment(timepoint).fromNow(),所以更新并非完全没有必要,我保证!
我以前有:
const FromNowString = ({ timePoint, ...rest }) => {
const [text, setText] = useState(formatTimeString(timePoint));
useEffect(() => {
setText(formatTimeString(timePoint));
let updateInterval = setInterval(
() => setText(formatTimeString(timePoint)),
30000
);
return () => {
clearInterval(updateInterval);
};
}, [timePoint]);
// Note the console log here is so we can see when renders occur
return (
<StyledText tagName="span" {...rest}>
{console.log('render') || text}
</StyledText>
);
};
这“有效” - 如果 props 更改,组件会正确更新,并且组件会在每个间隔更新,然而在安装时,并且当 props 更改时,组件将渲染两次。
这是因为useEffect 在timePoint 的值发生变化时运行 渲染结果,并且在我的useEffect 回调中我立即调用setState 方法来触发额外的渲染。
显然,如果我删除对setText 的调用,组件似乎不会在道具更改时发生更改(直到间隔运行),因为text 仍然相同。
我终于意识到我可以通过设置一个我实际上并不需要的状态变量来触发渲染,如下所示:
const FromNowString = ({ timePoint, ...rest }) => {
// We never actually use this state value
const [, triggerRender] = useState(null);
useEffect(() => {
let updateInterval = setInterval(() => triggerRender(), 30000);
return () => {
clearInterval(updateInterval);
};
}, [timePoint]);
return (
<StyledText tagName="span" {...rest}>
{console.log("render") || formatTimeString(timePoint)}
</StyledText>
);
};
这很完美,组件只在挂载时渲染一次,并且在 timePoint 属性更改时渲染一次,但感觉很hacky。这是正确的处理方式,还是我缺少什么?
【问题讨论】:
-
不清楚这个间隔的目的是什么。由于 timePoint 不会随时间变化,因此它会使用相同的数据重新渲染组件。请详细说明组件的预期行为。首选方式取决于此。
-
@estus - 抱歉,我没有包括在内,因为它是并不真正需要的外围信息。我已经添加了为什么我需要在编辑中更新,见上文。
标签: reactjs react-hooks