点击链接删除子组件

时间:2017-10-12 14:27:18

标签: javascript reactjs

我现在正在教自己做出反应,我有一个查看状态的组件,当添加新项目时,它会将子组件附加到自身。我现在要做的是通过单击删除添加的子组件。但是我似乎无法获得链接的自然事件停止,如果我e.preventDefault()我得到preventDefault不是未定义的函数。

以下是我的代码,

    import React, { Component } from 'react';
import InvoiceForm from './InvoiceForm';
import InvoiceItemForm from './InvoiceItemForm';

class GenerateInvoice extends Component {

  constructor(props) {
    super(props);
    this.state = {
      invoice: {
        items : []
      }
    };

    this.onAddChild = this.onAddChild.bind(this);
    this.removeItem = this.removeItem.bind(this);
  }

  render() {
    const children = [];
    for (var i = 0; i < this.state.invoice.items.length; i += 1) {
      children.push(
        <InvoiceItemForm 
          key={i} 
          number={i}
          remove={this.removeItem} />
      );
    }
    return(
      <div>
        <a href="" onClick={this.onAddChild}>Add New Item</a>
        {children}
      </div>
    )
  }

  removeItem = (e, itemIndex) => {
    e.stopPropagation();
    alert("..removing...");
    // let invoice = this.state.invoice;
    // let updatedItems = this.state.invoice.items.splice(index, 1); //remove element
    // let updateInvoice = { ...invoice, items:updatedItems}
    // this.setState({ invoice }); //update state
  }

  onAddChild = (e) => {
    e.preventDefault();
    let invoice = this.state.invoice;
    // creates an updated version of the items without changing the original value
    let updatedItems = invoice.items.push({ 'id': 'INV001' });
    // creates a new version of the invoice with the updated items
    let updateInvoice = { ...invoice, items: updatedItems };
    // update the invoice on the state to the new version
    this.setState({ invoice });
  }


}

导出默认的GenerateInvoice;

子组件

    import React from 'react';

const InvoiceItemForm = (props) => {
  console.log(props);
  return(
    <div>
      <p>Hello {props.number}</p>
      <a href="" onClick={props.remove(props.number)}>Remove</a>
    </div>
  )
}

export default InvoiceItemForm;

以及指向我的沙箱的链接

https://codesandbox.io/s/0qx9w1qrwv

2 个答案:

答案 0 :(得分:1)

InvoiceItemForm组件onClick={props.remove(props.number)}上,只有在这里您才能引用事件对象。

您可以更改为:

onClick={(e) => {
  e.preventDefault();
  props.remove(props.number);
}}

编辑:

如果您想避免在每次渲染时创建一个函数,可以使用以下内容:

class InvoiceItemForm extends React.Component {
  handleClick = (e) => {
    e.preventDefault();
    this.props.remove(props.number);
  }

  render() {
    console.log(this.props);
    return(
      <div>
        <p>Hello {this.props.number}</p>
        <a href="" onClick={this.handleClick}>Remove</a>
      </div>
    )
  }
}

答案 1 :(得分:0)

您应该绑定项目的索引以直接删除removeItem方法。

重构你的渲染方法:

render() {
  return(
    <div>
      <a href="" onClick={this.onAddChild}>Add New Item</a>
      {this.state.invoice.items.map((item, index) => {
        return (
          <InvoiceItemForm
            key={index}
            number={index}
            remove={this.removeItem.bind(null, index)}
          />
        );
      })}
    </div>
  );
}

这会将索引作为第一个参数绑定到在props中传递的removeItem函数,同时保持对象绑定不变(因此方法的上下文仍然是GenerateInvoice组件。由事件处理程序传递,它将显示为第二个参数。

所以处理程序定义应该是:

removeItem(index, e) {
  e.preventDefault();
  ...your removal code here...
}      

最后,子组件中的超级简单事件处理:

<a href="" onClick={props.remove}>Remove</a>

虽然我会使用<button>元素来删除整个默认事件处理&amp;完全传播。 <a>应专门用于导航内容。