用钩子反应本地计时器

时间:2019-11-11 10:50:45

标签: react-native react-hooks

我正在尝试创建一个带有钩子的计时器,但是当我启动该应用程序时,即使秒数低于0,它仍然只倒数秒。我找不到问题出在哪里

import React, { useState, useEffect } from 'react'
import { Text, View } from 'react-native'

export default App = () => {

  const [mins, setMins] = useState(2)
  const [secs, setSecs] = useState(2)

  useEffect(() => {
    setInterval(() => {
      if (secs <= 0) {
        if (mins <= 0) alert('end')
        else {
          setMins(m => m - 1)
          setSecs(59)
        }
      }
      else setSecs(s => s - 1)
    }, 1000)
  }, [])

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

      <Text style={{ fontSize: 40 }}>
        {mins}:{secs < 10 && 0}{secs}
      </Text>

    </View>
  )
}

2 个答案:

答案 0 :(得分:0)

这应该有效:

别忘了从useEffect返回并清除clearInterval。

import React, { useState, useEffect } from 'react'
import { Text, View } from 'react-native'

export default App = () => {

  const [mins, setMins] = useState(2)
  const [secs, setSecs] = useState(2)

  useEffect(() => {
    const timerId = setInterval(() => {
      if (secs <= 0) {
        if (mins <= 0) alert('end')
        else {
          setMins(m => m - 1)
          setSecs(59)
        }
      }
      else setSecs(s => s - 1)
    }, 1000)
    return () => clearInterval(timerId);
  }, [secs, mins])

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

      <Text style={{ fontSize: 40 }}>
        {mins}:{secs < 10 && 0}{secs}
      </Text>

    </View>
  )
}

答案 1 :(得分:0)

首先,React.useStatethis.setState一样,它是一个异步函数,您不应同时调用它们。
其次,React.useEffect类似于componentDidMountcomponentDidUpdatecomponentWillMount。您必须在条件不匹配时返回,并清除clearInterval。
我的解决方案代码如下:

import React, { useState, useEffect } from 'react'
import { Text, View } from 'react-native'

export default App = () => {

  const [time, setTime] = useState({mins:2,secs:2})


  useEffect(() => {
    if(time.mins<0){ if(timerId) {clearInterval(timerId)} return}
    const timerId = setInterval(() => {
      if (time.secs <= 0) {
        if (time.mins <= 0) {
        setTime({...time,mins:time.mins-1,secs:time.secs}) 
        alert('end')
        }
      else {
          setTime({...time,mins:time.mins-1,secs:59})
        }
      }
      else setTime({...time,mins:time.mins,secs:time.secs-1})
    }, 1000)
    return () => clearInterval(timerId);
  }, [time])

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

      <Text style={{ fontSize: 40 }}>
        {time.mins>=0 ? time.mins : 0}:{time.secs < 10 && 0}{time.secs}
      </Text>

    </View>
  )
}

但是对于本机建议方式,setState应该在组件中使用, 纯组件不应React.useState,如果需要,可以使用React。组件