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
相关产品推荐
相关产品推荐

