2016-06-27 4 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

코드 포맷을 수정했지만 먼저'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" 
    /> 
} 
관련 문제