This.setState не является функцией
У меня есть следующий компонент, который поддерживает состояние, которое обновляется, когда событие запускается в конкретном элементе, и когда состояние обновляется, оно передается в качестве опоры другому компоненту. В настоящее время я пытаюсь понять, почему возникает следующая ошибка: "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>
);
}
}
EDIT:
Я просто понял, что контекст изменяется, когда функция "onreadyStateChange", поэтому я сделал следующее в searchGif
searchGif(){
//other logic
var self = this;
xhr.onreadystatechange = function(){
//ajax logic
self.setState({results: repsonse});
}
}
Ответы
Ответ 1
Вы теряете класс 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();
}
}
удивительная вещь о функциях стрелок, они связывают ваш контекст для вас, и синтаксис также удивительный. Недостатком является поддержка браузера. Убедитесь, что у вас есть полифайл или процесс компиляции, чтобы скомпилировать его в синтаксис ES5 для кросс-браузерной производительности.
Если вы не можете сделать ни то, ни другое, просто сделайте теневую переменную вашего контекста this вне функции async onreadystatechange
и используйте ее вместо this
.
редактировать
Большинство компиляторов в наши дни обрабатывают методы привязки к классу стрелками (без указания преобразования babel... и т.д.), Вы также можете назначать состояние таким образом без конструктора
export default class SearchBox extends Component {
state = {
results: []
}
searchGif = (event) => {
// ... code here
xhr.onreadystatechange = () => {
// ... code here
this.setState();
}
}
render() {
// ...
}
}