登陆验证码组件(倒计时)的设计思路问题



  • 目前在做验证码登录,在实现中遇到问题。
    我的思路是该组件由登录输入和验证码倒计时button两个组件构成(登录输入组件与倒计时button是父子关系),验证码倒计时涉及到setInterval(),为了在倒计时到0时clearInterval(在componentWillReceiveProps),所以选择把倒计时button单拿出做一个组件,时间每减少一秒,改变父组件state(seconds),现在的问题是父组件重新渲染把电话号码也冲掉了,不知道该如何解决。
    form用的控件:tcomb-form-native

    代码如下:
    父组件:

    export default class Login extends Component {
    
      constructor(props) {
        super(props);
        this.state = {
            seconds: 60,
            isDisabled: false,
            tel:''
        }
      }
    
      onPress() {
        var value = this.refs.form.getValue();
        if(value && value.verify) {
          console.log('开始登陆');
        } else {
          console.log('请输入正确的手机号和验证码');
        }
      }
    
      countdown(seconds,isDisabled) {
        this.setState({seconds: seconds,isDisabled:isDisabled});
      }
    
      resetCount() {
        this.setState({seconds: 60,isDisabled:false})
      }
    
      render() {
        return (
          <View style={{flex:1,backgroundColor:'#f0f0f0'}}>
            <NavigationBar  title={{title:this.props.title}} 
                            leftButton={<Icon style={{paddingLeft: 10,paddingRight: 50}} name="arrow-back" size={26} color="#ff5a37" onPress={() => Actions.pop()} />}/>
            <View style={{padding: 10,justifyContent: 'center',backgroundColor:'#fff',marginTop:10}}>
              <Form ref="form" type={loginForm} options={options}/>
              <Verfiy seconds={this.state.seconds}
                      isDisabled={this.state.isDisabled}
                      countdown={(seconds,isDisabled)=>this.countdown(seconds,isDisabled)}
                      resetCount={()=>this.resetCount()}>
                {this.state.seconds}
              </Verfiy>
              <Button onPress={()=>this.onPress()}
                      style={{backgroundColor: '#ff5a37'}}
                      textStyle={{fontSize: 18}}>
                登陆
              </Button>
            </View>             
          </View>
        );
      }
    }
    
    子组件:
    export default class Verfiy extends Component {
    
      constructor(props) {
        super(props);
      }
    
      componentWillReceiveProps(nextProps) {
        if(nextProps.seconds==0) {
          this.interval && clearInterval(this.interval);
          this.props.resetCount();
        }
      }
    
      onPress() {
        this.interval = setInterval(() => {
          this.props.countdown(this.props.seconds - 1,true);
        }, 1000);
        this.props.onVerfiy();
      }
    
    
      render() {
        var content;
        if(this.props.seconds == 60) {
          content = '获取验证码';
        } else {
          content = '('+ this.props.seconds + ')重新获取';
        }
        return (
          <Button onPress={()=>this.onPress()}
                  style={{backgroundColor: '#ff5a37',width:150}}
                  textStyle={{fontSize: 18}}
                  isDisabled={this.props.isDisabled}>
            {content}
          </Button>
        );
      }
    }
    

  • administrators

    看不到你电话号码相关的state在哪。
    不了解你提到的这个form组件,我觉得这个用textinput来写一点也不麻烦。



  • @sunnylqm 获取验证码那个按钮点击后要倒计时60秒,为了clearInterval(在componentWillReceiveProps)我只能做个子组件,点击获取验证码,子组件中 this.interval = setInterval(() => {
    this.props.countdown(this.props.seconds - 1,true); //这个会更新父组件state中的seconds,然后把seconds子组件的属性传进来,从而实现倒计时,但此时父组件重新渲染,导致textinput中的电话没了,现在不知道怎么解决。。。
    }, 1000);

    请问您的思路是什么?不需要父子组件来实现吗?


  • administrators

    我说我看不到你电话号码相关的state在哪,所以不理解所谓的冲掉是个什么情况。父组件当然会重新渲染,但渲染的当然只会是与变化的state相关的那一部分,否则岂不全乱套了。



  • @sunnylqm 我明白了,是我弄错了,不变的state部分不会渲染。。。基本功不行,见笑了,谢谢你。


登录后回复