点击链接去除子组件

问题描述:

我在教自己做出反应的时候,我有一个组件查看状态,当添加一个新项目时,它将一个子组件添加到它自己。我现在要做的是通过点击删除添加的子组件。不过,我似乎无法得到链接的自然事件停止,如果我做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

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> 
    ) 
    } 
} 
+0

这可能是我曾经困惑过的,这是否会在每次重新渲染时创建一个新函数,因此效率低下? – Udders

+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> 
); 
} 

这将结合指数作为第一参数在道具传递的的removeItem功能,同时使对象的方法结合不变(这样的上下文。仍然在GenerateInvoice组件时,该事件由事件处理程序通过,将显示为第二个参数

所以处理器定义应该是:

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

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

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

虽然我会用一个<button>元素,而不是删除整个默认事件共处理&传播。 <a>应该专门用于导航内容。