2016-10-25 9 views
1

Ich habe eine Liste und ich möchte onClick-Ereignis festlegen, wenn auf ein Listenelement geklickt wird. Aber meine Funktion wird nicht ausgelöst, obwohl ich die Funktion gebunden habe.ReactJS onClick im Listenelement

Ich habe TODO Beispiel (TODO GITHUB) betrachtet. In diesem Beispiel wird onClick-Listenelement eine Aktion versenden und am Ende wird der Global State (Redux Store) geändert.

Was ich will ist, wenn ich auf Listenelement klicke, ändert es nicht den globalen Status, aber es ändert nur den lokalen Status. Ich habe lokalen Zustand und onClickItemHandler Funktion initialisieren, aber es scheint, dass meine Funktion nicht ausgeführt wird (kein console.log-Ergebnis in Chrome-Konsole).

Hier ist mein Code

// Searchable Component 
class Searchable extends Component{ 
    constructor(props,context){ 
    super(props); 
    this.state ={ 
     listAccount: [], 
     style:{ 
     searchResultList:{ 
      listStyle: 'none', 
      width: '100%', 
      height: '0em' 
     }, 
     searchResultItem:{ 
      listStyle: 'none', 
      width: '100%', 
      height: '0em' 
     }, 
     } 
    }; 

    this.onChange = this.onChange.bind(this); 
    this.onFocus = this.onFocus.bind(this); 
    this.onBlur = this.onBlur.bind(this); 
    this.onItemClickHandler = this.onItemClickHandler.bind(this); 
    } 

    onChange(event){ 
    this.props.onInputChange(this.props.data.type, this.props.data.id,event.target.value); 
    } 

    onFocus(event){ 
    console.log("input on focus"); 
    const showResultList= { 
     height: '10em', 
     overflow:'auto' 
    }; 

    const showResultItem= { 
     height: '2.4em', 
     visibility: 'visible' 
    }; 

    let style= this.state.style; 
    style.searchResultList = showResultList; 
    style.searchResultItem = showResultItem; 
    this.setState({style}); 
    } 

    onBlur(event){ 
    console.log("input on Blur"); 
    const showResultList= { 
     height: '0', 
     overflow:'hidden' 
    }; 

    const showResultItem= { 
     height: '0', 
     visibility: 'collapse' 
    }; 

    let style= this.state.style; 
    style.searchResultList = showResultList; 
    style.searchResultItem = showResultItem; 
    this.setState({style}); 
    } 

    onItemClickHandler(event){ 
    console.log("test"); 
    console.log(event.target); 
    } 

    render(){ 
    return(
     <div className="searchable"> 
     <input type="search" className="input-searchable" value={this.props.data.input} onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur}/> 
     <div className="search-result"> 
      <SearchResultList 
      ResultList={this.props.accounts} 
      listStyle={this.state.style.searchResultList} 
      listItemStyle={this.state.style.searchResultItem} 
      onClick={this.onItemClickHandler} 
      /> 
     </div> 
     </div> 
    ); 
    } 
} 

// SearchResultList Component 
const SearchResultList = ({ResultList, listStyle, listItemStyle, onClick}) => (
    <ul style={listStyle} onClick={onClick}> 
    { 
    ResultList.map((item,idx) => 
     <SearchResultItem 
     key={++idx} 
     style={listItemStyle} 
     text={item.name} 
     onClick={onClick} 
     /> 
    ) 
    } 
    </ul> 
); 


// SearchResultItem Component 
const SearchResultItem = ({ onClick, text, style}) => (
    <li 
    style={style} 
    onClick={onClick} 
    > 
    {text} 
    </li> 
); 

Antwort

2

Sie Ihre onClick Funktion binden müssen:

<SearchResultList 
     ResultList={this.props.accounts} 
     listStyle={this.state.style.searchResultList} 
     listItemStyle={this.state.style.searchResultItem} 
     onClick={::this.onItemClickHandler} 
    /> 

oder

<SearchResultList 
     ResultList={this.props.accounts} 
     listStyle={this.state.style.searchResultList} 
     listItemStyle={this.state.style.searchResultItem} 
     onClick={this.onItemClickHandler.bind(this)} 
    /> 

Sie tun das Gleiche versuchen, verbindlich dies zu Ihrer Funktion. Ich glaube, es wird beim Rendern ausgeführt, weil es nicht korrekt gebunden ist.

auch, falls Sie diese Methoden, um mehrere Kinder vorbei und sind besorgt über die Leistung, können Sie wie so im Konstruktor binden:

constructor(props) { 
    super(props) 
    this.onItemClickHandler = this.onItemClickHandler.bind(this) 
} 

dann

<SearchResultList 
     ResultList={this.props.accounts} 
     listStyle={this.state.style.searchResultList} 
     listItemStyle={this.state.style.searchResultItem} 
     onClick={this.onItemClickHandler} 
    /> 
+0

Gibt es etwas, was ich neben dem Binden der Funktion in der Funktion render() tun kann? –

+1

Weil ich denke, Binding-Funktion innerhalb der render() -Funktion wird Leistung (?) –

+0

Ich habe meine Antwort bearbeitet und adressiert Ihre Bedenken – jacoballenwood

0

verwenden Wenn Sie besorgt über die Leistung können Sie es7 Klasseneigenschaft verwenden. Sie müssen Ihre Funktion im Konstruktor auf diese Weise nicht manuell binden. Also TROCKEN yay !!

onItemClickHandler = (event) => { 
     console.log("test"); 
     console.log(event.target); 
    } 
+0

Facebook sagt, dass dies "experimentelle" Syntax ist, aber wenn es eingerichtet ist zu arbeiten, dann ist dies auch eine gute ! – jacoballenwood

+1

über Bindemethode, ich liebe die Verwendung reaktionslos funktionaler Komponente, dieser Artikel lehrte mich, warum [link] (https://medium.com/@housecor/react-stateless-functional-components-nine-wins-you-might-have -overlooked-997b0d933dbC# .wt8tnld3u) –

+0

Ja, es ist experimentell. Aber es ist hier zu bleiben :) – FlatLander

Verwandte Themen