I have the following component, which maintains the state that gets updated when the event is fired on the an specific element and when the state is updated it is passed down as a prop to another component. I am currently trying why i get the following error "this.setState is not a function", its most likely not binded to the right context. But i am unsure of this, am i doing this right?
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: I just realized the context gets changed when "onreadyStateChange" function, so i did the following in searchGif
searchGif(){
//other logic
var self = this;
xhr.onreadystatechange = function(){
//ajax logic
self.setState({results: repsonse});
}
}
You are losing the React class this
context. Bind it, and also bind it in the async callback function too.
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();
}
}
awesome thing about arrow functions is they bind your context for you and the syntax is awesome too. downside is browser support. Make sure you have a polyfil or a compile process to compile it into ES5 syntax for cross browser performance.
If you cant do either of those then just make a shadow variable of your this context outside of the async onreadystatechange
function and use it instead of this
.
Most compilers these days handle binding methods to the class with arrows (without specifying babel transforms ... etc), you can assign state as well this way without a constructor
export default class SearchBox extends Component {
state = {
results: []
}
searchGif = (event) => {
// ... code here
xhr.onreadystatechange = () => {
// ... code here
this.setState();
}
}
render() {
// ...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With