【问题标题】:create timer with react native using es6使用 es6 使用本机反应创建计时器
【发布时间】:2015-11-04 23:30:03
【问题描述】:

我希望在我的应用程序中添加一个计时器,该应用程序是使用 react native 构建的。

我在文档中查看了指向 timer mixin 的链接,但是我使用 es6 构建了应用程序的其余部分,因此这将不兼容。

我已经尝试了以下。

在我的 Main 类中,我有一个名为 getTimerCountDown 的函数

getTimerCountDown() {
    setTimeout(() => {
      this.setTimeRemaining(this.getTimeRem()-1);
    }, 1000);
}

getTimeRem() {
    return this.state.timeRemaining;
}

我尝试在componentDidUpdate 中调用它,如下所示。如果我不与 UI 进行任何其他交互,这将按我的意愿工作。

如果我这样做(例如,我有一个按钮,我可以点击视图。)当再次调用 `componentDidUpdate 时,conunter 变得非常快(因为它被调用了 x 次)

componentDidUpdate(){
    this.getTimerCountDown();
}

我不确定我是否完全走错了路,或者对我所做的事情进行微小的改变就能得到我想要的。 使用 es6 让倒数计时器在本机反应中工作的最佳方法是什么?

定时器类 在主页上

<Timer timeRem={this.getTimeRem()} />

返回

render(){
    return (
        <View style={styles.container}>
            <Text> This is the Timer : {this.props.setTimer}  - {this.props.timeRem} </Text>
        </View>
    )
}

【问题讨论】:

  • 尝试更改您的 getTimerCountdown 并使其返回 setState()
  • TimerMixin 的哪一部分不兼容?它的文档甚至使用了 es6 示例

标签: javascript ios facebook reactjs react-native


【解决方案1】:

即使没有任何其他 UI 交互,我也不确定它会如何工作。每次重新渲染组件时都会调用componentDidUpdate,当内部状态或传递的道具发生变化时会发生这种情况。不是你可以指望每秒钟都会发生的事情。

如何将getTimerCountDown 移动到您的componentDidMount 方法(仅调用一次),然后使用setInterval 而不是setTimeout 以确保计数器连续递减?

【讨论】:

  • 这个建议很有效,谢谢。在我设置了 getTimerCountDown 函数的上下文中,您将如何清除Interval?我不确定我将如何做到这一点,因为它通常分配给一个 var?
  • 您可以将计时器的引用存储在组件的状态或组件的成员变量中(如果后者被认为是不好的做法,则不是 100% - 如果您不需要该引用来渲染至少该组件)。然后,每当您需要停止计时器时,您都可以像往常一样在clearInterval 中传递该引用。这能回答你的问题吗?
  • 如果您想要一个简单的倒计时,这很有效,但由于setIntervalsetTimeout 的漂移方式,它在时间上是准确的。见stackoverflow.com/a/29972322/146612
【解决方案2】:

有点晚了,但是你可以试试我为在 react-native 中处理计时器和 es6 组件而制作的这个组件:

https://github.com/fractaltech/react-native-timer

想法很简单,维护和清除组件上的计时器变量很痛苦,所以很简单,将它们维护在一个单独的模块中。示例:

// not using ES6 modules as babel has broken interop with commonjs for defaults 
const timer = require('react-native-timer');

// timers maintained in the Map timer.timeouts 
timer.setTimeout(name, fn, interval);
timer.clearTimeout(name);

// timers maintained in the Map timer.intervals 
timer.setInterval(name, fn, interval);
timer.clearInterval(name);

// timers maintained in the Map timer.immediates 
timer.setImmediate(name, fn);
timer.clearImmediate(name);

// timers maintained in the Map timer.animationFrames 
timer.requestAnimationFrame(name, fn);
timer.cancelAnimationFrame(name);

【讨论】:

    【解决方案3】:

    试试这个

    Timer.js

    import React, { Component } from "react";
    import { View,Text,Button,StyleSheet } from "react-native";
    const timer = () => {};
    class Timer extends Component {
        constructor(props) {
        super(props);
        this.state = {
          remainingTime: 10
         };
        }
    
     countdownTimer(){
       this.setState({remainingTime:10 });
       clearInterval(timer);
       timer = setInterval(() =>{
            if(!this.state.remainingTime){
              clearInterval(timer);
              return false;
            }
            this.setState(prevState =>{
            return {remainingTime: prevState.remainingTime - 1}});
            },1000);
        }
    
        render() {
          return (
           <View style={styles.container}>
             <Text>Remaining time :{this.state.remainingTime}</Text>
              <Button title ="Start timer" onPress={()=>this.countdownTimer()}/>
           </View>
         );
       }
      }
    
    
      const styles = StyleSheet.create({
        container:{
         flex:1,
         justifyContent:'center',
         alignItems:'center',
       } 
    });
    
      export default Timer;
    

    App.js

    import React, { Component } from "react";
      import { View,Text,Button,StyleSheet } from "react-native";
      import Timer from './timer';
    
      export default class App extends Component{
       render(
        return (<Timer />)
       );
     }
    

    【讨论】:

    • 干得好!干得好!!
    【解决方案4】:

    这里是如何在 react-native 中创建计时器(番茄钟计时器)的完整代码;

    Timer.js

    import React from 'react'
    import {Vibration, View, Button, Text, TextInput, StyleSheet} from 'react-native'
    
    
    let pomInterval;
    
    export default class Timer extends React.Component {
        constructor() {
            super();
            this.state = {
                minutes: 5,
                seconds: 0,
                workmins: 5,
                worksecs: 0,
                breakMins: 2,
                breakSecs: 0,
                timerState: 'WORK TIMER',
                btnState: 'Start'
            }
        }
    
        vibrate = () => {
            Vibration.vibrate([500, 500, 500])
        }
    
        pomTimer = () => {
            pomInterval = setInterval(() => {
                let newSec = this.state.seconds;
                newSec--;
                if(newSec < 0) {
                    newSec = 59;
                    this.state.minutes--;
                }
                this.setState({
                    seconds: newSec,
                })
    
                if(newSec <= 0 && this.state.minutes <= 0) {
                    this.vibrate();
                    if(this.state.timerState == 'WORK TIMER') {
                        this.setState({
                            timerState: 'BREAK TIMER',
                            minutes: this.state.breakMins,
                            seconds: this.state.breakSecs
                            
                        })
                    }else {
                        this.setState({
                            timerState: 'WORK TIMER',
                            minutes: this.state.workmins,
                            seconds: this.state.worksecs
                        })
                    }
                }
            }, 1000);
        }
    
    
        changeWorkMin = mins => {
            clearInterval(pomInterval);
            this.setState({
                minutes: mins || 0,
                workmins: mins || 0,
                btnState: 'Start'
            })
        }
    
        changeWorkSec = secs => {
            clearInterval(pomInterval);
            this.setState({
                seconds: secs || 0,
                worksecs: secs || 0,
                btnState: 'Start'
            })
        }
    
        changeBreakMin = mins => {
            clearInterval(pomInterval);
            this.setState({
                breakMins: mins || 0,
                btnState: 'Start'
            })
        }
    
        changeBreakSec = secs => {
            clearInterval(pomInterval);
            this.setState({
                breakSecs: secs || 0,
                btnState: 'Start'
            })
        }
    
        // Creating the functionality for the pause/start button
        chnageBtnState = () => {
            if(this.state.btnState == 'Start') {
                this.pomTimer();
                this.setState({
                    btnState: 'Pause'
                })
    
            }else {
                clearInterval(pomInterval);
                this.setState({
                    btnState: 'Start'
                })
            }
        }
    
        // Creating the functionality for the reset button
        reset = () => {
            clearInterval(pomInterval);
            if(this.state.timerState == 'WORK TIMER') {
                this.setState({
                    minutes: this.state.workmins,
                    seconds: this.state.worksecs,
                    btnState: 'Start'
                })
            }else {
                this.setState({
                    minutes: this.state.breakMins,
                    seconds: this.state.breakSecs,
                    btnState: 'Start'
                })
            }
        }
    
        render() {
            return (
                <View style={styles.viewStyles}>
                    <Text style={styles.textStyles}>{this.state.timerState}</Text>
                    <Text style={styles.textStyles}>{this.state.minutes}:{this.state.seconds}</Text>
                    <Text>
                        <Button title={this.state.btnState} onPress={this.chnageBtnState} />
                        <Button title='Reset' onPress={this.reset} />
                    </Text>
                    <Text>Work Time:</Text>
                    <TextInput style={styles.inputStyles} value={this.state.workmins.toString()} placeholder='Work Minutes' onChangeText={this.changeWorkMin} keyboardType='numeric' />
                    <TextInput style={styles.inputStyles} value={this.state.worksecs.toString()} placeholder='Work Seconds' onChangeText={this.changeWorkSec} keyboardType='numeric' />
                    <Text>Break Time:</Text>
                    <TextInput style={styles.inputStyles} value={this.state.breakMins.toString()} placeholder='Break Minutes' onChangeText={this.changeBreakMin} keyboardType='numeric' />
                    <TextInput style={styles.inputStyles} value={this.state.breakSecs.toString()} placeholder='Break Seconds' onChangeText={this.changeBreakSec} keyboardType='numeric' />
                </View>
            )
        }
    }
    
    // Creating a style sheet to write some styles
    const styles = StyleSheet.create({
        viewStyles: {
            alignItems: 'center'
        },
    
        textStyles: {
            fontSize: 48
        },
    
        inputStyles: {
            paddingHorizontal: 50,
            borderColor: 'black',
            borderWidth: 1
        }
    })
    

    App.js

    import React from 'react';
    import { StyleSheet, Text, View } from 'react-native';
    import Timer from './timer';
    
    export default function App() {
      return (
        <View style={styles.container}>
          <Timer />
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
      },
    });
    

    这就是我们创建番茄钟计时器的方法,该计时器同时具有工作计时器和休息计时器,它会在其中一个计时器到达其结束时振动手机。我还添加了输入功能,即您可以动态更改分钟和秒的值(无论是工作定时器还是休息定时器)。我还添加了一个开始/暂停按钮和一个重置按钮。

    【讨论】:

      猜你喜欢
      • 2021-05-26
      • 2020-03-07
      • 2019-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-20
      • 1970-01-01
      相关资源
      最近更新 更多