【问题标题】:How to calculate difference between two moments in react native如何在本机反应中计算两个时刻之间的差异
【发布时间】:2021-02-17 11:40:44
【问题描述】:

我正在尝试计算持续时间(两个时刻之间的差异),例如,目前我正在处理一个 react native 项目,在该项目中我必须计算在屏幕/卡片上花费的时间。 所以现在我正在尝试这样计算花费的时间:

import moment from 'moment';
// lets say i have 3 states to note time
const [startTime, setStartTime] = useState(moment());
const [endTime, setEndTime] = useState(moment());
const [elapsedTime, setElapsedTime] = useState(Number);

// assume i have a bottomSheet, so whenever that bottom sheet goes up the timer starts and when it goes down to original position, timer stops and calculate difference/duration in minutes.
// so for the onOpenStart on onCloseEnd props of the bottomsheet, this is my function:


const start = () => {
  setStartTime(moment());
}

const end = () => {
  setEndTime(moment());
  const et = moment.duration(endTime.diff(startTime)).asSeconds();
  setElapsedTime(et);
  console.log(elapsedTime) // if i try for 10 seconds it logs 34, or sometimes -6, it's just not right
}

我尝试使用new Date 方法,如果我尝试 10 秒,它会记录 34,有时是 -6,这是不对的,但无法成功... 任何帮助将不胜感激。

【问题讨论】:

    标签: javascript react-native momentjs


    【解决方案1】:

    在您的特定情况下,我认为您甚至不需要 moment 库。它在捆绑包中非常重,只是不需要。

    1. 您不需要使用日期初始化状态。当组件刚刚安装时,您不关心它们,是吗?您希望跟踪函数 startend 被触发的日期。

    2. 当前的行为是这样的,因为useState 是异步的。这意味着您正在尝试设置状态,然后在下一行中使用该值进行一些计算 - 这将不起作用。

    3. 您可以做的是使用useRef 而不是useState。这样,您将确保您拥有的值是整个组件中最新鲜的值。

       const startTime = useRef(new Date());
       const endTime = useRef(new Date());
       const [elapsedTime, setElapsedTime] = useState();
      
       const start = () => {
         startTime.current = new Date();
       }
      
       const end = () => {
         endTime.current = new Date();
         const et = (startTime.current - endTime.current) / 1000 // get the seconds
         setElapsedTime(et);
         console.log(et); // You cannot log elapsedTime here, because again, useState is async
        }
      
    4. 我不知道您需要对经过的时间做什么,您可能也不需要状态。现在我将其保留为状态。

    5. 最后一件事:我真的建议查看 day.js 库,因为它的功能(在 99% 的情况下)与 moment 相同,但要轻得多。

    【讨论】:

    • 嘿,我试过了,但是在启动函数中出现了一些错误,Type 'Date' is not assignable to type 'null' ...
    • 你在使用打字稿吗?我从来没有使用过它,但是从 useRef 的初始化中删除null,应该可以。或者用 new Date() 初始化它。
    • 是的,那我觉得没关系,还是这样
    • 我已经在初始化中添加了日期。
    【解决方案2】:

    useState 不会同步更新。这意味着虽然您设置了EndTime,然后尝试读取它,但它可能还没有更新。

    另外,设置状态会导致重新渲染。这在衡量性能时是不必要的。您可以改用useRef 将计时值保存在参考变量中。

    export default function App() {
      const [visible, setVisible] = React.useState(false);
      const timer = React.useRef(null)
    
      return (
        <View style={styles.container}>
          <Pressable
            onPress={() => {
              timer.current = new Date().getTime()
              setVisible(true);
            }}>
            <Text>Show modal</Text>
          </Pressable>
          <Pressable
            onPress={() => {
              setVisible(false);
              alert(new Date().getTime() - timer.current)
            }}>
            <Text>Hide modal</Text>
          </Pressable>
    
          {visible ? (
            <Card>
              <Text>Modal content</Text>
            </Card>
    
          ) : null}
        </View>
      );
    }
    

    在这里,我们设置可见值并在按下时存储时间戳。而当用户按下 hide 时,我们使用存储的时间来计算经过的时间。

    【讨论】:

    • 嘿,我尝试了你的解决方案,但它在timer.current 线上给出了一个类型错误,说`Type 'number' is notassignable to type 'null'。
    • 你好像在使用 Typescript,你可以通过设置联合类型来解决这个问题:const timer = React.useRef&lt;null | number&gt;(null)
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多