2017-05-09 28 views
0

我正在使用react-bootstrap-typeahead asynchronous searching。在renderMenuItemChildren方法中,我想調用另一個方法handleSubmit來獲取所選項目的詳細信息。'this'undefined in renderMenuItemChildren

thisrenderMenuItemChildren內部未定義,我無法調用該方法。任何幫助表示讚賞。

P.S.我仍然在學習反應,所以可能會有一個我無法辨認的愚蠢錯誤。

class App extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     searchTitle: '', 
     defaultUrl: 'http://www.omdbapi.com/?t=arrival' 
    }; 
    this.handleSearch = this.handleSearch.bind(this); 
    this.handleSubmit = this.handleSubmit.bind(this); 
    this.fetchApiData = this.fetchApiData.bind(this); 
    } 

    componentDidMount() { 
    this.fetchApiData(this.state.defaultUrl); 
    } 

    fetchApiData(url){ 
    fetch(url) 
    .then((result) => { 
     return result.json() 
    }) 
    .then((json) => { 
     if(json.Response === "True"){ 
      this.setState({ 
      title: json.Title, 
      year: json.Year, 
      released: json.Released, 
      runtime: json.Runtime, 
      genreList: json.Genre, 
      actors: json.Actors, 
      plot: json.Plot, 
      poster_url: json.Poster, 
      rating: json.imdbRating, 
      boxOffice: json.BoxOffice, 
      votes: json.imdbVotes, 
      response: json.Response 
     }); 
     } 
     else { 
     this.setState({ 
      response: json.Response, 
      error: json.Error 
     }); 
     } 
    }) 
    .catch((err) => { 
     console.log(err); 
    }) 
    } 

    handleSubmit(query){ 
    if (!query) { 
     return; 
    } 
    this.fetchApiData(`http://www.omdbapi.com/?t=${query}`); 
    } 

    handleSearch(query) { 
    if (!query) { 
     return; 
    } 

    fetch(`http://www.omdbapi.com/?s=${query}`) 
     .then((result) => { 
     return result.json() 
     }) 
     .then((json) => { 
     //console.log(json.Search); 
     this.setState({ 
      options: json.Search 
     }) 
     }); 
    } 

    renderMenuItemChildren(option, props, index) { 
    return (
     <div key={option.imdbID} onClick={() => 
     this.handleSubmit.bind(option.Title)}> 
     <span>{option.Title}</span> 
     </div> 
    ); 
    } 

    render() { 
    return (
     <div className="row"> 
     <div className="col-xs-12 col-lg-10 col-lg-offset-1"> 
      <div className="App-header col-xs-12"> 
      <div className="row"> 
       <div className="col-xs-12 col-sm-6 col-lg-5"> 
       <h1><a href="http://www.omdbapi.com/" className="omdb-link" title="The Open Movie Database">OMDb</a></h1> 
       </div> 
       <div className="col-xs-12 col-sm-6 col-lg-7"> 

       <AsyncTypeahead 
        ref="typeahead" 
        {...this.state} 
        labelKey="Title" 
        onSearch={this.handleSearch} 
        options={this.state.options} 
        placeholder='Search Title' 
        className="search-input-box" 
        renderMenuItemChildren={this.renderMenuItemChildren} 
       /> 
       </div> 
      </div> 
      </div> 
      <SearchBody data={this.state} /> 
     </div> 
    </div> 
    ); 
    } 
    } 

回答

0

你不需要=>功能在這裏。您可以使用下面的代碼來傳遞標題值回handleSubmit()

renderMenuItemChildren(option, props, index) { 
    return (
    <div key={option.imdbID} onClick={this.handleSubmit.bind(this, option.Title)}> 
     <span>{option.Title}</span> 
    </div> 
); 
} 
+0

感謝您的解決方案。雖然這並沒有完全起作用,但我必須像@ T.J所建議的那樣綁定renderMenuItemChildren。 Crowder –

+0

理想情況下,您不需要在調用時和構造函數中的位置綁定它。其中任何一個都應該足夠。但無論如何,我很高興這個解決方案對你有所幫助。 – ivp

2

您需要的功能renderMenuItemChildren綁定在構造以及:

補充一點:

this.renderMenuItemChildren = this.renderMenuItemChildren.bind(this); 

這是一個可愛的小博客帖子有幾種方法可以這樣:Blog Post 那說我更喜歡lodash的bindAll:

_.bindAll(this, function1, function2, function3)

+1

感謝鏈接到博客文章:) –

1

你需要做的你已經在你的構造函數其他方法(handleSearchhandleSubmit等)做了什麼:

this.renderMenuItemChildren = this.renderMenuItemChildren.bind(this); 

(或幾個其他的方式,但是這是你正在使用的方式爲你的其他方法,所以...)

+0

謝謝你,renderMenuItemChildren是AsyncTypeahead的方法,所以我想我可能不需要綁定。 –

1

雖然renderMenuItemChildren.bind(this)在構造函數中肯定會工作,ES6類還允許您使用箭頭函數表達式作爲類方法。這會自動將this(換言之,上下文)綁定到方法,減少樣板代碼的數量,並使組件更易於閱讀。

所以,你的代碼可能是這樣的:

class App extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     searchTitle: '', 
     defaultUrl: 'http://www.omdbapi.com/?t=arrival' 
    }; 
    } 

    // etc... 

    renderMenuItemChildren =() => { 
    // do stuff 
    } 
}