我有以下组件,它维护在特定元素上触发事件时更新的状态,并且当状态更新时,它作为prop传递给另一个组件。我目前正在尝试为什么我得到以下错误“this.setState不是一个函数”,它很可能没有绑定到正确的上下文。但我不确定这一点,我这样做对吗?
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(
<div>
<input className="search-input" ref="query" onKeyDown={this.searchGif.bind(this)} name="search" placeholder="Search"/>
<GifSwatch data={this.state.results} />
</div>
);
}
}
修改 我刚刚意识到当“onreadyStateChange”函数时上下文被改变了,所以我在searchGif中做了以下
searchGif(){
//other logic
var self = this;
xhr.onreadystatechange = function(){
//ajax logic
self.setState({results: repsonse});
}
}
答案 0 :(得分:56)
您正在丢失React类this
上下文。绑定它,也将它绑定在异步回调函数中。
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();
}
}
关于箭头函数的很棒的事情是它们为你绑定你的上下文,语法也很棒。缺点是浏览器支持。确保您有一个polyfil或编译过程,将其编译为ES5语法以实现跨浏览器性能。
如果您不能执行其中任何一项,那么只需在异步onreadystatechange
函数之外创建此上下文的阴影变量,然后使用它而不是this
。
现在大多数编译器都使用箭头处理类的绑定方法(没有指定babel变换等等),你可以在没有构造函数的情况下以这种方式分配状态
export default class SearchBox extends Component {
state = {
results: []
}
searchGif = (event) => {
// ... code here
xhr.onreadystatechange = () => {
// ... code here
this.setState();
}
}
render() {
// ...
}
}