2017-05-09 15 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 
    } 
}