Reactjs componentWillUnmount 没有被调用

标签 reactjs

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

但是,当呈现 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 更改时,所有先前未安装的选项也会监听事件。

输入字段--

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,

}

我知道这个事件服务很糟糕,它只是为了快速测试这个功能。

最佳答案

Field 组件保持安装状态,在这种情况下您需要使用 keys识别哪个组件已更改、添加或删除:

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

关于Reactjs componentWillUnmount 没有被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38052402/

相关文章:

reactjs - react 表列隐藏

javascript - react 复选框显示不正确的值

reactjs - 如何清理单页应用程序上的嵌入式 youtube 订阅按钮

javascript - Fixed-data-table-2 - React 不更新表格单元格

javascript - Browserify 需要 imperavi 编辑器

reactjs - rtk 查询突变被拒绝

javascript - React-router 不变违规 : The root route must render a single element

javascript - React Redux - 无法使用将组件的方法传递给子组件 - 未定义错误

android - 组合多个导航的 react 导航

node.js - 如何在单个液滴上将不同的 MERN 应用程序部署到 digital ocean ?