2017-10-12 16 views
0

私は自分自身を教えています。状態を調べるコンポーネントがあり、新しいアイテムが追加されると子コンポーネントが追加されます。私が今しようとしているのは、クリックして追加された子コンポーネントを削除することです。しかし、私が行う場合、私はリンクの自然な出来事を得るように見えることはできません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。 InvoiceItemFormコンポーネント、onClick={props.remove(props.number)}

子コンポーネント

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

答えて

1

、ここだけ、あなたは、イベントオブジェクトへの参照を持っています。

あなたが好きなものにに変更することができます。

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

EDIT:

あなたは、各レンダリング機能を作成しないようにしたい場合は、あなたのようなものを使用することができます

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

あなたはそうです。私の編集を参照してください。私は自分の意見では、それぞれのレンダリングがそれほど悪くない新しい機能を作成すると言いますが、それを避けることはマイクロ最適化です。 –

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関数へ最初引数としてインデックスをバインドする(そうメソッドのコンテキストになります。あなたのrenderメソッドをリファクタリング

。。GenerateInvoiceコンポーネント残るイベントがイベントハンドラによって渡されると、それは2番目の引数として表示されます

だから、ハンドラ定義は次のようになります。

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

と子コンポーネントの取り扱いついに超シンプルなイベント:

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

私は完全に&伝播を扱う全体のデフォルトのイベントを削除する代わりに<button>要素を使用することになりますが。 <a>は、コンテンツのナビゲートにのみ使用する必要があります。

関連する問題