关于javascript:this.setState不是函数

this.setState is not a function

本问题已经有最佳答案,请猛点这里访问。

我有以下组件,它维护在特定元素上触发事件时得到更新的状态,当状态更新时,它作为一个属性传递给另一个组件。我正在尝试为什么会出现以下错误:"this.setstate不是函数",它很可能没有绑定到正确的上下文。但我对此不确定,我做得对吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
export default class SearchBox extends Component{

    constructor(){
        super()
        console.log("search box imported");
        this.state = {
            results:[]
        };
    }

    //this.setState({result: arrayExample})

    searchGif(event) {
        if(event.keyCode == 13){
            let inputVal = this.refs.query.value;
            let xhr = new XMLHttpRequest();
            xhr.open('GET', 'http://api.giphy.com/v1/gifs/search?q='+inputVal+'&api_key=dc6zaTOxFJmzC', true);
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4 && xhr.status == 200){
                    // this.response = JSON.parse(xhr.responseText);
                    let returnedObj = JSON.parse(xhr.responseText);
                    //console.log(returnedObj.data);
                    let response = returnedObj.data.map(function(record){
                        let reformattedArray =  {   key: record.id,
                                                    id: record.id,
                                                    thumbnailUrl: record.images.fixed_height_small_still.url
                                                };
                                                return reformattedArray;
                    });
                    console.log(response);
                    this.setState({results: response});
                }
            }
            xhr.send();
        }
    }


    render(){

        return(
               
                <input className="search-input" ref="query" onKeyDown={this.searchGif.bind(this)} name="search" placeholder="Search"/>
                <GifSwatch data={this.state.results} />
           
        );
    }
}

编辑:我刚意识到当"onreadystatechange"函数时上下文会发生变化,所以我在searchgif中做了以下操作

1
2
3
4
5
6
7
8
searchGif(){
   //other logic
   var self = this;
   xhr.onreadystatechange = function(){
    //ajax logic
    self.setState({results: repsonse});
   }
}


您将丢失react类this上下文。绑定它,也可以在异步回调函数中绑定它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
constructor(props){
    super(props);
    console.log("search box imported");
    this.state = {
        results:[]
    };
    this.searchGif = this.searchGif.bind(this);
}

searchGif(event) {
    // ... code here
    xhr.onreadystatechange = () => {
    // ... code here
        this.setState();
    }
}

关于arrow函数,最棒的是它们为您绑定了上下文,而且语法也非常棒。缺点是浏览器支持。确保您有一个polyfil或编译过程将其编译为ES5语法,以提高跨浏览器性能。

如果您不能这样做,那么只需在异步onreadystatechange函数之外创建一个此上下文的影子变量,并使用它而不是this

编辑

现在大多数编译器都使用箭头来处理类的绑定方法(不指定babel转换…等等),您也可以这样分配状态,而不需要一个构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default class SearchBox extends Component {
  state = {
    results: []
  }

  searchGif = (event) => {
    // ... code here
    xhr.onreadystatechange = () => {
    // ... code here
        this.setState();
    }
  }
  render() {
    // ...
  }
}