this.setState 不是函数 [英] this.setState is not a function
问题描述
我有以下组件,它维护在特定元素上触发事件时更新的状态,当状态更新时,它作为道具传递给另一个组件.我目前正在尝试为什么我收到以下错误this.setState 不是函数",它很可能没有绑定到正确的上下文.但我不确定这一点,我这样做对吗?
export default class SearchBox extends Component{构造函数(){极好的()console.log("导入的搜索框");this.state = {结果:[]};}//this.setState({result: arrayExample})searchGif(事件){如果(事件.keyCode == 13){让 inputVal = this.refs.query.value;让 xhr = 新的 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);让returnedObj = JSON.parse(xhr.responseText);//console.log(returnedObj.data);让响应 = ReturnObj.data.map(function(record){让 reformattedArray = { 键:record.id,id: 记录.id,缩略图网址:record.images.fixed_height_small_still.url};返回重新格式化数组;});控制台日志(响应);this.setState({results: response});}}xhr.send();}}使成为(){返回(<div><input className="search-input" ref="query" onKeyDown={this.searchGif.bind(this)} name="search" placeholder="Search"/><GifSwatch 数据={this.state.results}/>
);}}
我刚刚意识到当onreadyStateChange"函数时上下文发生了变化,所以我在 searchGif 中做了以下操作
searchGif(){//其他逻辑var self = this;xhr.onreadystatechange = function(){//ajax逻辑self.setState({结果:回复});}}
您正在丢失 React 类 this
上下文.绑定,也在异步回调函数中绑定.
构造函数(道具){超级(道具);console.log(导入的搜索框");this.state = {结果:[]};this.searchGif = this.searchGif.bind(this);}searchGif(事件){//... 代码在这里xhr.onreadystatechange = () =>{//... 代码在这里this.setState();}}
箭头函数很棒的一点是它们为你绑定了你的上下文,而且语法也很棒.缺点是浏览器支持.确保您有一个 polyfil 或编译过程将其编译为 ES5 语法以实现跨浏览器性能.
如果您不能执行其中任何一个,那么只需在异步 onreadystatechange
函数之外创建一个 this 上下文的影子变量,并使用它代替 this
.
编辑
现在大多数编译器都使用箭头处理类的绑定方法(不指定 babel 转换等),您也可以通过这种方式分配状态而无需构造函数
export default class SearchBox extends Component {状态 = {结果: []}searchGif = (事件) =>{//... 代码在这里xhr.onreadystatechange = () =>{//... 代码在这里this.setState();}}使成为() {//...}}
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
.
Edit
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() {
// ...
}
}
这篇关于this.setState 不是函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!