You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ComponentDidMount失效及手机号提交按钮状态异常问题求助

问题分析与解决方案

让我们一步步解决你的两个核心问题:

1. 提交后输入新手机号时按钮状态异常

这个问题的根源是弹窗打开时没有重置表单状态。当你提交完手机号后,组件的phone和disabled状态还保留着上次的数值(比如disabled: false),所以下次打开弹窗时按钮会先处于启用状态,输入第一个字符后因为长度不够才被禁用。

修复方案:在弹窗打开时重置state

修改handleOpen方法,当弹窗被打开时,强制重置表单的初始状态:

handleOpen = () => {
  const newOpenState = !this.props.open;
  this.props.dispatch({ type: 'ADD_MANAGER_MODAL', payload: newOpenState });
  
  // 打开弹窗时重置手机号和按钮禁用状态
  if (newOpenState) {
    this.setState({ phone: '', disabled: true });
  }
};

2. 添加componentDidMount后应用崩溃

你原来的componentDidUpdate代码存在语法和逻辑双重错误:

  • if ({ disabled: false && this.state.phone < 10 }) 这里错误地创建了一个对象,而非进行布尔判断
  • this.state.phone是字符串类型,不能直接用<10比较长度,应该用.length属性
  • 更关键的是,这个方法完全多余——你已经在输入框的onChange事件里处理了按钮禁用逻辑,不需要额外的生命周期方法重复检查

修复方案:移除错误的生命周期方法

直接删掉componentDidUpdate和checkPhoneFields方法,避免无效逻辑引发的崩溃。

额外优化:避免直接操作DOM

你当前通过document.getElementById获取输入值的方式不符合React的状态管理理念,容易引发不可预期的bug。我们可以优化为完全通过state管理表单数据:

修改handleChange和PhoneMask组件

handleChange = (value) => {
  // 清理手机号中的非数字字符
  const cleanedPhone = value.replace(/[(.)\s]/g, '');
  this.setState({
    phone: value,
    // 当清理后的长度不等于10时,禁用按钮
    disabled: cleanedPhone.length !== 10
  });
};

PhoneMask = () => {
  return (
    <MaskedInput
      mask={phoneNumber}
      placeholderChar={'\\u2000'}
      placeholder="Phone Number"
      id="add-manager-phone"
      className="masked-input"
      value={this.state.phone} // 绑定state中的值
      onChange={(e) => {
        this.handleChange(e.target.value);
      }}
    />
  )
}

修改提交按钮的点击事件

用state中的值替代DOM查询:

<SpinnerButton
  id="invite-new-manager"
  variant="raised"
  color="primary"
  disabled={this.state.disabled}
  onClick={() => props.addAdmin(
    this.state.phone.replace(/[(.)\s]/g, ''), // 直接从state获取并清理手机号
    show.eid,
    'invite-new-manager'
  )}
  label="Invite"
/>

完整修改后的代码

import React from 'react'
import { Dialog, Button, TextField } from 'material-ui'
import { connect } from 'react-redux'
import { inviteAdminByPhone } from '../db'
import MaskedInput from 'react-text-mask'
import { phoneNumber } from '../masks'
import SpinnerButton from '../components/spinner-button'
import { CircularProgress } from 'material-ui/Progress'

class AddManagerModal extends React.Component {
  state = { 
    disabled: true, 
    phone: '' 
  }

  handleOpen = () => {
    const newOpenState = !this.props.open;
    this.props.dispatch({ type: 'ADD_MANAGER_MODAL', payload: newOpenState });
    
    if (newOpenState) {
      this.setState({ phone: '', disabled: true });
    }
  }

  handleChange = (value) => {
    const cleanedPhone = value.replace(/[(.)\s]/g, '');
    this.setState({
      phone: value,
      disabled: cleanedPhone.length !== 10
    });
  };

  PhoneMask = () => {
    return (
      <MaskedInput
        mask={phoneNumber}
        placeholderChar={'\\u2000'}
        placeholder="Phone Number"
        id="add-manager-phone"
        className="masked-input"
        value={this.state.phone}
        onChange={(e) => {
          this.handleChange(e.target.value);
        }}
      />
    )
  }

  render() {
    const props = this.props
    const show = props.show
    const phone = this.state.phone

    return (
      <div>
        <Dialog open={props.open} onBackdropClick={() => this.handleOpen()}>
          <div className="dialog-padding max-width-300">
            <h3 className="oswald font-light tal mb0">Managers Phone Number</h3>
            <TextField 
              value={phone} 
              fullWidth 
              className="max-width-250" 
              InputProps={{ inputComponent: this.PhoneMask }} 
            />
          </div>
          <div className="dialog-padding tar">
            <Button 
              variant="flat" 
              color="secondary" 
              onClick={() => this.handleOpen()} 
            > 
              Cancel 
            </Button>
            <SpinnerButton 
              id="invite-new-manager" 
              variant="raised" 
              color="primary" 
              disabled={this.state.disabled}
              onClick={() => props.addAdmin(
                this.state.phone.replace(/[(.)\s]/g, ''),
                show.eid,
                'invite-new-manager'
              )} 
              label="Invite" 
            />
          </div>
        </Dialog>
      </div>
    )
  }
}

const mapStateToProps = state => {
  return { 
    open: state.addManagerModal, 
    show: state.show 
  }
}

const mapActionToProps = dispatch => {
  return { 
    dispatch, 
    addAdmin: (number, event_id, id) => dispatch(inviteAdminByPhone(number, event_id, id)) 
  }
}

const connector = connect(mapStateToProps, mapActionToProps)
export default connector(AddManagerModal)

这些修改应该能彻底解决你的两个问题,同时让代码更符合React的状态管理最佳实践。

内容的提问来源于stack exchange,提问作者Troy Nelson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:24:11