11/*
2- * A smart countdown component for react-native apps. You may use it to handle different status when request a verification code.
2+ * A smart countdown component for react-native apps.
3+ * You may use it to handle different status when request a verification code.
34 * https://github.com/ljunb/react-native-countdown/
45 * Released under the MIT license
56 * Copyright (c) 2017 ljunb <cookiejlim@gmail.com>
@@ -10,7 +11,8 @@ import {
1011 StyleSheet ,
1112 Text ,
1213 TouchableOpacity ,
13- ViewPropTypes
14+ ViewPropTypes ,
15+ AppState
1416} from 'react-native' ;
1517
1618/**
@@ -31,40 +33,37 @@ export default class Countdown extends Component {
3133 title : PropTypes . string ,
3234 time : PropTypes . number ,
3335 overTitle : PropTypes . string ,
34- titleStyle : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . number ] ) ,
36+ titleStyle : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . number , PropTypes . array ] ) ,
3537 countingStyle : ViewPropTypes . style ,
3638 countingTitleTemplate : PropTypes . string ,
37- countingTitleStyle : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . number ] ) ,
39+ countingTitleStyle : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . number , PropTypes . array ] ) ,
3840 shouldHandleBeforeCountdown : PropTypes . func
3941 } ;
4042
4143 static defaultProps = {
4244 title : '获取短信验证码' ,
4345 time : 30 ,
44- countingTitleTemplate : '{time}s后重新获取' ,
4546 overTitle : '重新获取' ,
47+ countingTitleTemplate : '{time}s后重新获取' ,
4648 shouldHandleBeforeCountdown : ( ) => true
4749 } ;
4850
4951 constructor ( props ) {
5052 super ( props ) ;
53+ this . recodTime = 0 ;
5154 this . state = {
5255 second : props . time ,
5356 status : CountdownStatus . None
5457 }
5558 }
5659
57- shouldComponentUpdate ( nextProps , nextState ) {
58- const { time, title, overTitle, countingTitleTemplate} = this . props ;
59- const { second, status} = this . state ;
60-
61- const isNewComp = nextProps . title !== title || nextProps . time !== time || nextProps . overTitle !== overTitle || nextProps . countingTitleTemplate !== countingTitleTemplate ;
62- const isCounting = nextState . second !== second || nextState . status !== status ;
63- return isNewComp || isCounting ;
60+ componentDidMount ( ) {
61+ AppState . addEventListener ( 'change' , this . handleAppState ) ;
6462 }
6563
6664 componentWillUnmount ( ) {
6765 this . clearTimer ( ) ;
66+ AppState . removeEventListener ( 'change' , this . handleAppState ) ;
6867 }
6968
7069 stopCountdown = ( ) => {
@@ -74,16 +73,34 @@ export default class Countdown extends Component {
7473 } , this . clearTimer ) ;
7574 } ;
7675
76+ handleAppState = nextAppState => {
77+ if ( nextAppState === 'inactive' ) {
78+ this . recodTime = new Date ( ) ;
79+ this . clearTimer ( ) ;
80+ } else if ( nextAppState === 'active' ) {
81+ if ( this . state . status !== CountdownStatus . Counting ) return ;
82+
83+ const now = new Date ( ) ;
84+ const diff = Math . round ( ( now - this . recodTime ) / 1000 ) ;
85+ if ( this . state . second - diff <= 0 ) {
86+ this . setState ( { status : CountdownStatus . Over , second : this . props . time } ) ;
87+ } else {
88+ this . setState ( {
89+ status : CountdownStatus . Counting ,
90+ second : this . state . second - diff
91+ } , this . startTimer )
92+ }
93+ }
94+ } ;
95+
7796 handlePress = ( ) => {
7897 const { shouldHandleBeforeCountdown, countingTitleTemplate} = this . props ;
79- const { status} = this . state ;
80-
8198 const canStartTimer = shouldHandleBeforeCountdown ( ) ;
82- if ( status === CountdownStatus . Counting || ! canStartTimer ) return ;
83- if ( countingTitleTemplate . indexOf ( '{time}' ) === - 1 ) {
84- console . warn ( '[rn-countdown] The countingTitleTemplate string must conform to the format that contain `{time}`!' ) ;
85- }
99+ if ( ! canStartTimer ) return ;
86100 this . setState ( { status : CountdownStatus . Counting } , this . startTimer ) ;
101+
102+ const showWarn = countingTitleTemplate . indexOf ( '{time}' ) === - 1 ;
103+ showWarn && console . warn ( '[rn-countdown] The countingTitleTemplate string must conform to the format that contain `{time}`!' ) ;
87104 } ;
88105
89106 startTimer = ( ) => {
0 commit comments