简体   繁体   English

onChange of <select>子组件中的元素未在React中重新呈现父状态,警告:未安装的组件

[英]onChange of <select> element in child component not re-rendering the parent state in React, Warning: unmounted component

I'm lifting state up from child to parent and trying to render select elements with data from HTTP request. 我将状态从子级提升到父级,并尝试使用HTTP请求中的数据呈现选择元素。 The select tag values within the Inv child component will show previously selected values, but I'm getting this error: Inv子组件中的选择标记值将显示以前选择的值,但是出现此错误:

Warning: Can't call setState (or forceUpdate) on an unmounted component. 警告:无法在已卸载的组件上调用setState(或forceUpdate)。 This is a no-op, but it indicates a memory leak in your application. 这是空操作,但它表明应用程序中发生内存泄漏。 To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method. 要解决此问题,请在componentWillUnmount方法中取消所有订阅和异步任务。

It looks like the error is coming from the Inv child component that is being passed props with this.state.identInvsData . 看起来错误来自Inv子组件,该子组件正在使用this.state.identInvsData传递给道具。 That is the only time I get the error. 那是我唯一的错误。 The child components in the else statements that don't get the identInvsData don't get that error message. else语句中未获得identInvsData的子组件不会获得该错误消息。 The parent component does not re-render, or "mount" the children. 父组件不会重新渲染或“装载”子组件。
Any ideas as to what I'm doing wrong? 关于我在做什么错的任何想法吗?

Edit: The child components are populating the data from HTTP endpoint, but onChange it doesn't change the values in setState , only when I select the button Add Inv . 编辑:子组件正在从HTTP端点填充数据,但是onChange不会更改setState的值,只有当我选择按钮Add Inv It adds another child but also allows the previous children to change. 它添加了另一个孩子,但也允许以前的孩子进行更改。

Identity Parent Component 身份父组件

class Identity extends React.Component {  

      state = {
        invIds: [],
        inTypes: [],
        invSeqIds: [],
        numChildren: 0,
        addInvBtnPressed: false
      };

      handleAddInv = () => {
        this.setState({
          numChildren: this.state.numChildren + 1,
          addInvBtnPressed: true
        });
      };

      onChangeInv = (e, index, sId) => {
        const invIdsArry = this.state.invIds;
        const invSeqIdsArry = this.state.invSeqIds;
        const newId = [
          ...invIdsArry.slice(0, index),
          (invIdsArry[index] = e.target.value),
          ...invIdsArry.slice(index + 1)
        ];
        if (sId) {
          const newSeqId = [
            ...invSeqIdsArry.slice(0, index),
            (invSeqIdsArry[index] = sId),
            ...invSeqIdsArry.slice(index + 1)
          ];
          this.setState({ invIds: newId, invSeqIds: newSeqId });
        } else {
          this.setState({ invIds: newId });
        }
      };

      onChangeType = (e, index) => {
        const invTypesArry = this.state.invTypes;
        const newTypes = [
          ...invTypesArry.slice(0, index),
          (invTypesArry[index] = e.target.value),
          ...invTypesArry.slice(index + 1)
        ];
        this.setState({ invTypes: newTypes });
      };


      render() {
        const children = [];
        var i;
        if (this.state.identInvsData && !this.state.addInvBtnPressed) {
          for (i = 0; i < this.state.numChildren; i += 1) {
            children.push(
              <Inv
                key={i}
                invKey={i}
                onChangeInv={this.onChangeInv.bind(this)}
                onChangeType={this.onChangeType.bind(this)}
                invId={this.state.identInvsData[i].invId}
                invType={this.state.identInvsData[i].invTypeCd}
                seqId={this.state.identInvsData[i].seqId}
                invData={this.state.identInvsData[i]}
              />
            );
          }
        } else if (this.state.identInvsData && this.state.addInvBtnPressed) {
          for (i = 0; i < this.state.numChildren; i += 1) {
            children.push(
              <Inv
                key={i}
                invKey={i}
                onChangeInv={this.onChangeInv.bind(this)}
                onChangeType={this.onChangeType.bind(this)}
              />
            );
          }
        } else {
          for (i = 0; i < this.state.numChildren; i += 1) {
            children.push(
              <Inv
                key={i}
                invKey={i}
                onChangeInv={this.onChangeInv.bind(this)}
                onChangeType={this.onChangeType.bind(this)}
              />
            );
          }
        }
        return (
          <div>
            <button
              type="button"
              className="btn btn-info"
              onClick={this.handleAddInv}
            >
              Add Inv
            </button>
            <div>{children}</div>
          </div>
        )
    }
}
export default Identity;

Inv Child Component Inv子组件

class Inv extends React.Component {

    state = {
      kddLookupData: "",
      invData: ""
    };

    componentDidMount = () => {
      kddlookups_getAll().then(resp => {
        this.setState({
          kddLookupData: resp.data.item
        });
      });
      invs_getAll().then(resp => {
        this.setState({
          invData: resp.data.items
        });
      });
    };

    handleInvestigatorChange = e => {
      this.props.onChangeInv(e, this.props.invKey, this.props.seqId);
    };

    handleInvestigatorTypeChange = e => {
      this.props.onChangeType(e, this.props.invKey);
    };

    render() {
      return (
        <div>
          <select
            value={this.props.invId}
            name={this.props.invKey}
            onChange={this.handleInvChange.bind(this)}
          >
            <option className="blank">Select inv name:</option>
            {this.state.invData &&
             this.state.invData.map(inv => {
                return (
                   <option key={inv.userId} value={inv.userId}>
                      {inv.invName}
                   </option>
                );
              })}
          </select>

          <select
            value={this.props.invType}
            name={this.props.invKey}
            onChange={this.handleInvTypeChange.bind(this)}
          >
            <option className="blank">Select inv type:</option>
            {this.state.kddData &&
             this.state.kddData.kdd_inv_type.map(inv => {
               return (
                  <option key={inv.inv_type_cd} value={inv.inv_type_cd}>
                     {inv.inv_type_name}
                  </option>
               );
             })}
          </select>
        </div>
    )
  }
}
export default Inv;

It doesn't look like you are returning anything in your render function in the child component. 看起来您没有在子组件的render函数中返回任何内容。 Try: 尝试:

render() {
return (
   <div>
      <select
        value={this.props.invId}
        name={this.props.invKey}
        onChange={this.handleInvChange.bind(this)}
      >
        <option className="blank">Select inv name:</option>
        {this.state.invData &&
         this.state.invData.map(inv => {
            return (
               <option key={inv.userId} value={inv.userId}>
                  {inv.invName}
               </option>
            );
          })}
      </select>

      <select
        value={this.props.invType}
        name={this.props.invKey}
        onChange={this.handleInvTypeChange.bind(this)}
      >
        <option className="blank">Select inv type:</option>
        {this.state.kddData &&
         this.state.kddData.kdd_inv_type.map(inv => {
           return (
              <option key={inv.inv_type_cd} value={inv.inv_type_cd}>
                 {inv.inv_type_name}
              </option>
           );
         })}
      </select>
      </div>
   );
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM