reactjs componentWillUnmount未被调用

时间:2016-06-27 11:08:36

标签: reactjs react-jsx

我已经构建了一个表单,其中有下拉列表,将显示下面的字段。所以说,首先选择了optionSet1,其中有3个字段要显示。如果用户更改下拉菜单以选择optionSet2,则会显示不同的选项集。

但是,当呈现optionSet2并删除optionSet1时,它应该为先前呈现的每个componentWillUnmount调用InputFields,但事实并非如此。永远不会调用此函数。

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 个答案:

答案 0 :(得分:1)

我明白了。什么时候开始&#34;解开&#34;组件通过状态,它们必须具有关键属性。

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