2016-06-27 16 views
3

フォームをビルドしました。ここにドロップダウンがあり、フィールドの下のどの選択項目が表示されますか。つまり、最初にoptionSet1が選択され、3つのフィールドが表示されていたとします。ユーザーがドロップダウンを変更してoptionSet2を選択すると、異なるオプションセットが表示されます。reactjs componentWillUnmountが呼び出されていません

しかし、optionSet2がレンダリングされ、optionSet1が削除された場合は、それ以前にレンダリングされたそれぞれに対して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

私はあなたのコードの書式を修正しましたが、最初に 'return'メソッドを' render'メソッドに追加しましたが、欠落した '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" 
    /> 
} 
関連する問題