2017-10-12 2 views
0

Ich lehre mich reagieren im Moment, ich habe eine Komponente, die den Zustand betrachtet und wenn ein neues Element hinzugefügt wird, hängt es eine untergeordnete Komponente an sich. Ich versuche jetzt, die hinzugefügte untergeordnete Komponente durch einen Klick zu entfernen. Jedoch kann ich nicht scheinen, das natürliche Ereignis einer Verbindung zu stoppen, wenn ich e.preventDefault() mache, bekomme ich preventDefault ist keine Funktion von undefined.Entfernen Sie die untergeordnete Komponente beim Klicken auf den Link

Unten ist mein Code,

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


} 

Exportstandard GenerateInvoice;

Kind Komponente

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; 

und ein Link zu meinem Sandkasten,

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

Antwort

1

Auf der InvoiceItemForm Komponente, onClick={props.remove(props.number)}, hier nur haben Sie den Verweis auf das Ereignisobjekt.

können Sie auf etwas ändern wie:

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

EDIT:

Wenn Sie eine Funktion vermeiden möchten, dass jeder zu schaffen machen, können Sie so etwas wie verwenden:

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

Vielleicht, wo ich verwirrt bin, schafft dies eine neue Funktion auf jedem Rendern und ist daher ineffizient? – Udders

+0

Sie haben Recht. Siehe meine Bearbeitung. Ich muss sagen, dass das Erstellen einer neuen Funktion meiner Meinung nach nicht so schlecht ist, es zu vermeiden ist eine Mikrooptimierung. –

0

Sie sollten den Index des Elements binden, um ihn direkt an die Methode removeItem zu entfernen.

Refactoring Ihre Render-Methode:

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

Dies wird den Index als erste Argument an die removeItem Funktion binden, die in den Stützen geleitet, während das Objekt verbindlich unangetastet bleiben (so den Kontext für die Verfahren .. die GenerateInvoice Komponente bleibt, wenn das Ereignis durch den Ereignishandler übergeben wird, es als zweites Argument wird zeigen, bis

so sollte die Handler Definition sein:

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

Und schließlich die Super einfache Ereignis in der Komponente Kindern Handhabung:

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

Obwohl ich würde stattdessen ein <button> Element verwenden, um die gesamten Standard-Event-Handling & Vermehrung ganz zu entfernen. <a> sollte ausschließlich zum Navigieren von Inhalten verwendet werden.

Verwandte Themen