2016-06-27 214 views
3

我已经建立了一个窗体,其中有下拉选项,将显示下面的字段。所以说,首先optionSet1被选中,其中有3个字段显示。如果用户更改下拉列表以选择optionSet2,则会显示不同的选项集。reactjs componentWillUnmount没有被调用

但是,当optionSet2正在呈现并且optionSet1被删除时,它应该为之前呈现的每个InputFields调用componentWillUnmount,但情况并非如此。这个功能从来没有被调用。

class LeadUpdate extends React.Component { 
    constructor(props, context) { 
    super(props, context); 
    } 

    _getUpdateFields() { 
    let fields = this.props.inputFields[this.state.updateType]; 

    return _.map(fields, f => { 
     _.assignIn(f, { 
     fieldParentClass: 'form-group col-lg-6', 
     eventName: this.state.eventName 
     }); 
     return <InputField config={f} /> 
    }); 
    } 

    _onChange(id, value) { 
    this.setState({ 
     optionSet: value 
    }); 
    } 

    render() { 
    return (<div> 
     <div className="col-lg-5"> 
     <form role="form" className="vymo-form"> 
      <InputField values={this.props.values} onChange={this._onChange.bind(this)} /> 
     </form> 
     </div> 

     <div className="row"> 
     <form role="form" className="vymo-form"> 
      {this._getUpdateFields()} 
     </form> 
     </div> 
    </div>) 
    } 
} 

更新:我刚刚意识到componentWillUnmount被调用,但实际的问题是与eventListner。我在这里粘贴代码。

问题 - 我正在使用nodejs事件来获取来自不同输入字段的值。但是,当optionSet更改所有以前的卸载选项也正在侦听事件。

InputField -

import eventsService from '../../../services/events-service'; 

class InputField extends React.Component { 

    constructor(props, context) { 
     super(props, context); 

     this.state = { 
      id: this.props.id, 
      value: this._getInputFieldValue() || '', 
      valid: true, 
      errorVisible: false, 
      errorMessage: '' 
     }; 
    } 

    componentWillMount() { 
     if(this.props.eventName) { 
      this._subscription = eventsService.emitter.addListener(this.props.eventName, this._validate.bind(this)); 
     } 
    } 

    componentWillUnmount() { 
     if(this.props.eventName) { 
      eventsService.emitter.removeListener(this.props.eventName, this._validate.bind(this)); 
     } 
    } 

    _handleChange(event) { 

     if(this.props.onChange) { 
      this.props.onChange.call(null, this.state.id, event.target.value); 
     } 
     this.setState({ 
      value: event.target.value 
     }); 
    } 

    _getClasses(classes) { 
     if (classes) { 
      return classes.join(' '); 
     } 
    } 

    _getInputFieldProps() { 
     let inputProps = { 
      value: this.state.value, 
      type: this.props.type, 
      placeholder: this.props.placeholder || '', 
      id: this.props.id, 
      onChange: this._handleChange.bind(this), 
      className: this._getClasses(this.props.classes) ? this._getClasses(this.props.classes) + 'form-control' : 'form-control', 
      maxlength: this.props.maxLength, 
      disabled: this.props.disabled ? "true" : null, 
      min: this.props.min, 
      max: this.props.max, 
      readOnly: this.props.readonly ? "true" : null, 
      required: this.props.required 
     }; 

     return inputProps; 
    } 

    _validate(result) { 
     if (this.props.required && !this.state.value) { 
      valid = false; 
      this.setState({ 
       errorVisible: true, 
       errorMessage: 'this is required field', 
       valid: false 
      }); 
     } 


     if(valid) { 
      this.setState({ 
       errorVisible: false, 
       errorMessage: 'this is not a valid phone number', 
       valid: true 
      }); 
     } 

     result.valid &= valid; 
     result.values.push({ 
      type: this.props.type, 
      code: this.state.id, 
      value: this.state.value, 
      name: this.props.label 
     }); 


    } 

    _getInputFieldValue() { 
     switch (this.props.type) { 
      case Types.NUMBER: 
      case Types.EMAIL: 
      case Types.DECIMAL: 
      case Types.PHONE: 
      case Types.TEXT: 
       return this.props.value; 
     } 
    } 

    render() { 
     let props = this._getInputFieldProps(); 
     return (<div className={this.props.fieldParentClass}> 
      <label for={this.props.id}><span>{this.props.label}</span><span>{props.required ? '*' : ''}</span></label> 
      <input {...props}/> 
      <span className={this.state.errorVisible ? 'show' : 'hide'}>{this.state.errorMessage}</span> 
     </div>) 
    } 

} 

事件服务: -

import {EventEmitter} from 'events'; 
//TODO make this as constant 
var emmiter = new EventEmitter(); 
export default { 
    emitter: emmiter, 

} 

我理解这个事件服务是坏,它只是为快速测试此功能。

+1

您能否请分享更多的信息?我没有在这里看到'componentWillUnmount',并且render()没有返回正确的语法。谢谢。 – Grgur

+0

是的,删除了不必要的代码。只是为了简单起见。用div包装它,现在它会返回有效的html。 @Grgur – user2696466

+0

我解决了你的代码格式问题,但是我首先为你的'render'方法添加了一个'return',但是我再次移除了它,以防缺少'return'与你的问题相关。 – demux

回答

1

我想通了。当通过状态“取消渲染”组件时,它们必须具有关键属性。

{this.state.mode === 'custom' ? 
    <Field 
     label="A" 
     name="requested_completes" 
     type="number" 
     key="a" 
    /> 
    : 
    <Field 
     label="B" 
     name="requested_completes" 
     type="dropdown" 
     key="b" 
    /> 
}