尽管在构造函数(React)中有适当的绑定,'this'对象仍未定义

时间:2018-03-16 04:49:29

标签: javascript reactjs this setstate

我刚开始使用React,正在构建一个通过Youtube API合并视频搜索的应用。我在查询视频API后,尝试在“搜索结果”div中动态呈现视频数据。

这个“搜索结果”div应该呈现一个名为searchResults的JSX数组,它存储为AddSong组件的状态键值对。在组件构造时,这个数组是空的,它应该被填充在axios get请求的.then(function(response){}函数中(在我的搜索函数中)。

在此功能中,我逐项从API响应中提取相关数据。对于每个项目,我将数据格式化为JSX,并将其存储到名为vidComponents的本地数组中。当我调用this.setState({searchResults:vidComponents})时出现问题。 '这个'未定义。确切的错误如下所示:

TypeError:无法读取未定义

的属性'setState'

在做了一些研究后,我了解到大多数人因为没有在构造函数中正确地将“this”绑定到相关函数而得到此错误,但对我来说情况并非如此。 'this'在构造函数中绑定到我的搜索函数,如下所示:

this.search = this.search.bind(this)

有谁知道导致此错误的原因是什么?这是我的代码:

import React, { Component } from 'react';
import axios from 'axios';
import { FormGroup, FormControl, Button } from 'react-bootstrap';
import './add-song-component.css';

class AddSong extends React.Component{
    constructor(props, context){
        super(props, context);

        // Must bind this to functions in order for it to be accessible within them
        this.handleTextChange = this.handleTextChange.bind(this);
        this.search = this.search.bind(this);

        // Object containing state variables
        this.state = {
            searchText: '',
            searchResults: [],
            nextPageToken: ''
        };
    }

    // Keeps track of the current string in the search bar
    handleTextChange(e){
        this.setState({ searchText: e.target.value });
    }

    // Runs a search for 10 youtube videos through youtube's API
    search(e){
        // Initialize important data for formatting get request url
        var api = this.props.apiKey;
        var query = this.state.searchText;
        var maxResults = 10;

        // Execute get request on Youtube's search API
        axios.get('https://www.googleapis.com/youtube/v3/search', {
            params: {
                part: 'snippet',
                type: 'video',
                order: 'viewCount',
                key: api,
                q: query,
                maxResults: maxResults
            }
        })
        .then(function (response) {
            console.log(response.data);

            var vidComponents = [];

            // Loop through video data, extract relevant info
            var i = 0;
            for (let vidInfo of response.data.items) {
                vidComponents.push(
                    <div key={i}>
                        <p>title: {vidInfo.snippet.title}</p>
                        <p>channel: {vidInfo.snippet.channelTitle}</p>
                        <p>id: {vidInfo.id.videoId}</p>
                        <p>thumbnailUrl: {vidInfo.snippet.thumbnails.high.url}</p>
                    </div>
                );
                i++;
            }

            // Set searchResults state to account for new results...
            // Set nextPageToken state based on value from youtube's response
            // *** used for retrieving more videos from initial query ***
            this.setState({
                searchResults: vidComponents,
                nextPageToken: response.data.nextPageToken
            });
        })
        .catch(function (error) {
            console.log(error);
        }); 
    }

    render(){
        return(
            <div className="add-song">
                <form>
                    <FormGroup controlId="SearchText">
                        <FormControl 
                            type="text"
                            placeholder="Search for a song / video"
                            value={this.state.searchText}
                            onChange={this.handleTextChange}
                        />
                    </FormGroup>
                    <Button onClick={this.search}>Search</Button>
                </form>

                <div className="search-results">
                    {this.state.searchResults}
                </div>
            </div>
        );
    }
}

export default AddSong; 

3 个答案:

答案 0 :(得分:1)

恕我直言,您的For Each rw In sheet.Rows If rw.Cells(1, 1).Value = "<YOUR STRING HERE>" Then ... Next rw search函数在构造函数中的作用域都很好。那应该不是问题。但我确实在handleSearch func:

中看到setState

search

如果您可以使用箭头功能,那会更好!

axios.get(...).then(function() { this.setState(...) }

答案 1 :(得分:0)

handleTextChange = e => {
    this.setState({ searchText: e.target.value });
}

此语法将this绑定到当前类。在您的情况下,this将指向当前的函数范围,因此您将获得undefined

答案 2 :(得分:0)

您缺少this绑定到handleTextChange函数的内容。因此,未使用Component this对象调用它。

解决方案1:在构造函数中使用绑定

constructor(props, context){
        super(props, context);
       //...
       this. handleTextChange = this.handleTextChange.bind(this);
}

解决方案2:使用 arrow function

handleTextChange =(e)=>{
        this.setState({ searchText: e.target.value });
    }