【问题标题】:'this' object undefined despite proper binding in constructor function (React)'this' 对象未定义,尽管在构造函数中正确绑定(React)
【发布时间】:2018-08-25 02:05:53
【问题描述】:

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

这个“search-results” 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; 

【问题讨论】:

  • 你调试过你的代码吗?
  • 问题在 axios .then 方法里面,你需要绑定它才能访问里面的this,像这样:.then((response) =&gt; {....}
  • Event中的this指的是Event所属的Object。换句话说,元素。
  • 你是对的,Mayank。谢谢!

标签: javascript reactjs this setstate


【解决方案1】:

恕我直言,您的 search 和 handleSearch 函数在构造函数中的作用域都很好。那应该不是问题。但我确实在您的 search 函数中看到了 setState:

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

如果你可以使用箭头功能会更好!

axios.get(...).then(() =&gt; { this.setState(...) }

【讨论】:

    【解决方案2】:

    您缺少this 绑定到您的handleTextChange 函数。因此,它没有被组件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 });
        }
    

    【讨论】:

    • 不,这不是原因。查看this.setState 的作用域
    • @Andrew 是的,它的范围为 AddSong 组件 this.but 在调用时。 handleTextChange 它没有绑定到组件 this
    • @RIYAJKHAN,该代码没有问题,问题在这一行:.then(function (response) {,OP 忘记绑定 axios .then 方法。应该是.then((response) =&gt; {..}
    【解决方案3】:
    handleTextChange = e => {
        this.setState({ searchText: e.target.value });
    }
    

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

    【讨论】:

    • 该代码没有问题,问题在这一行:.then(function (response) {,OP 忘记绑定 axios .then 方法。应该是.then((response) =&gt; {
    猜你喜欢
    • 2017-09-13
    • 1970-01-01
    • 2013-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    相关资源
    最近更新 更多