【问题标题】:How can you trigger a rerender of a React js component every minute?如何每分钟触发一次 React js 组件的重新渲染?
【发布时间】:2020-06-12 22:33:12
【问题描述】:

背景:
定义了一个钩子并返回一个对象,该对象包含最后一次修改文件的时间戳。

我计算从时间戳到现在的差异,以向用户显示距离他们上次保存的时间。

const StageFooter = (props) => {
  const [, , meta] = useMetadata("Tenant Setup Data", "setupData")

  return (
    <StageControls>
      <div id="footer-start"></div>
      <SavingBlock key={meta?.modified}>
        {`Last saved ${
          meta.modified !== undefined ? formatDistanceToNow(meta.modified) : " "
        } ago`}
      </SavingBlock>
      <div id="footer-end"></div>
    </StageControls>
  )
}

export default StageFooter


问题:
到现在为止计算出的时间戳差异不会实时更新。例如,它会说“最后保存 10 分钟前”,但几分钟后字符串仍然保持不变。只有当用户离开页面然后返回或用户刷新页面时,它才会更新。

考虑到这一切,我基本上希望每过一分钟就重新渲染组件,以便实时更新值。

感谢您的宝贵时间!

【问题讨论】:

  • 这不是 react 应该如何工作的——当最后保存的值更新时,它应该触发 react 生命周期更新,或者通过像 redux 使用的动作处理程序,或者响应说,一个 websocket播送。拥有基于计时器的更新在这里是一种反应反模式。我希望我能提供更多帮助,但我还没有使用钩子
  • 为什么不使用 Moment.js?它完全符合您的要求。我不会为此每时每刻都重新渲染我的组件。

标签: javascript reactjs components react-hooks


【解决方案1】:

您可以创建一个每分钟调用setTimeout 的效果,在显示时间时,只需减去日期即可。

您还应该为此创建一个单独的组件,因此如果您在组件中使用它,它不会“每分钟”重新渲染孔组件,而只会重新渲染文本“自上次更改以来的 x 分钟”

const [fakeCurrentDate, setFakeCurrentDate] = useState(new Date()) // default value can be anything you want

useEffect(() => {
    setTimeout(() => setFakeCurrentDate(new Date()), 60000)
}, [fakeCurrentDate])

...

{/* display time passed since*/}
<div>{fakeCurrentDate - modifiedDate}</div>

工作中codesandbox(您需要等待一分钟才能看到更改)

但正如 Sterling Archer 在 cmets 中所说,这样好吗?嗯……谁知道呢?


建议

另一种方法是显示一条消息Updated at XX:XX time,而不是向用户显示已经过去了多少分钟。但这更多的是关于用户体验而不是技术

【讨论】:

    【解决方案2】:

    我建议跟踪自组件初始挂载以来经过的时间,并以一定的时间间隔更新它。然后我们显示经过的时间,考虑到初始值并加上收到初始值后经过的时间(因为安装了组件)。

    export const Time = () => {
        // This would be the initial time. We can get it from a hook
        // (meta.modified in your case) or for this example from a ref.
        // I'm setting this to 2000 meaning it was updated 2 seconds ago.
        const initial_time = useRef(2000);
        const [time_passed, setTimePassed] = useState(0);
    
        useEffect(() => {
            const interval_time = 1000;
    
            // Set an interval that will update every interval_time
            const myInterval = setInterval(
                () => setTimePassed(time => time + interval_time),
                interval_time
            );
    
            // Clear the interval when the component unmounts
            return () => clearInterval(myInterval);
        }, []);
    
        return initial_time.current + time_passed;
    };
    

    为了以友好的方式显示经过的时间,请检查this other question

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-11
      • 1970-01-01
      • 2020-11-20
      • 2021-09-19
      • 2020-06-02
      • 2014-08-22
      • 1970-01-01
      • 2021-12-01
      相关资源
      最近更新 更多