两个button放在同一行_从同一功能的八种实现,谈谈 react 中的逻辑复用进化过程...

cd9ba04c69c091261989b14b7ef52ae2.png
需求:我们现在有一个获取验证码的按钮,需要在点击后禁用,并且在按钮上显示倒计时60秒才可以进行第二次点击。 本篇文章通过对这个需求的八种实现方式来讨论在 react 中的逻辑复用的进化过程

代码例子放在了 codesandbox 上。

方案一 使用 setInterval

import React from 'react'

export default class LoadingButtonInterval extends React.Component {
    
  state = {
    
    loading: false,
    btnText: '获取验证码',
    totalSecond: 10
  }
  timer = null
  componentWillUnmount() {
    
    this.clear()
  }
  clear = () => {
    
    clearInterval(this.timer)

    this.setState({
    
      loading: false,
      totalSecond: 10
    })
  }
  setTime = () => {
    
    this.timer = setInterval(() => {
    
      const {
     totalSecond } = this.state
      if (totalSecond <= 0) {
    
        this.clear()
        return
      }
      this.setState(() => ({
    
        totalSecond: totalSecond - 1
      }))
    }, 1000)
  }
  onFetch = () => {
    
    this.setState(() => ({
     loading: true }))
    const {
     totalSecond } = this.state
    this.setState(() => ({
    
      totalSecond: totalSecond - 1
    }))
    this.setTime()
  }
  render() {
    
    const {
     loading, btnText, totalSecond } = this.state
    return (
      <button disabled={
    loading} onClick={
    this.onFetch}>
        {
    !loading ? btnText : `请等待${
    totalSecond}秒..`}
      </button>
    )
  }
}

方案二 使用 setTimeout

import React from 'react'

export default class LoadingButton extends React.Component {
    
  state = {
    
    loading: false,
    btnText: '获取验证码',
    totalSecond: 60
  }
  timer = null

  componentWillUnmount() {
    
    this.clear()
  }
  clear = () => {
    
    clearTimeout(this.timer)

    this.setState({
    
      loading: false,
      totalSecond: 60
    })
  }
  setTime = () => {
    
    const {
     totalSecond } = this.state
    if (totalSecond <= 0) {
    
      this.clear()
      return
    }
    this.setState({
    
      totalSecond: totalSecond - 1
    })
    this.timer = setTimeout(() => {
    
      this.setTime()
    }, 1000)
  }
  onFetch = () => {
    
    this.setState(() => ({
     loading: true }))
    this.setTime()
  }
  render() {
    
    const {
     loading, btnText, totalSecond } = this.state
    return (
      <button disabled={
    loading} onClick={
    this.onFetch}>
        {
    !loading ? btnText : `请等待${
    totalSecond}秒..`}
      </button>
    )
  }
}

我们可能很快就写出来两个这样的组件。使用 setTimeout 还是 setInterval 区别不是特别大。 但是我会更推荐 setTimeout 因为 万物皆递归(逃)

不过,又有更高的要求了。可以看到刚刚我们的获取验证码。如果说再有一个页面有相同的需求,只能将组件完全再拷贝一遍。这肯定不合适嘛。

那咋办嘛?

方案三 参数提取到 Props 1

import React from "react";
class LoadingButtonProps extends React.Component {
    
  constructor(props) {
    
    super(props);
    this.initState = {
    
      loading: false,
      btnText: this.props.btnText || "获取验证码",
      totalSecond: this.props.totalSecond || 60
    };
    this.state = {
     ...this.initState };
  }
  timer = null;
  componentWillUnmount() {
    
    this.clear();
  }
  clear = () => {
    
    clearTimeout(this.timer);
    this.setState({
    
      ...t
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值