Реагируй родной таймер с крючками - PullRequest
0 голосов
/ 11 ноября 2019

Я пытаюсь сделать таймер с перехватами, но когда я запускаю приложение, оно все еще считает только секунды, даже если секунды ниже 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 голосов
/ 11 ноября 2019

Во-первых, React.useState, как и this.setState, это асинхронная функция, вы не должны вызывать их одновременно.
Во-вторых, React.useEffect, как componentDidMount, componentDidUpdate,componentWillMount. вы должны вернуться, когда ваше условие не совпадает, и 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. Компонент

0 голосов
/ 11 ноября 2019

Это должно работать:

Не забудьте вернуться с 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>
  )
}
...