this.setState 不是函数 [英] this.setState is not a function

查看:24
本文介绍了this.setState 不是函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下组件,它维护在特定元素上触发事件时更新的状态,当状态更新时,它作为道具传递给另一个组件.我目前正在尝试为什么我收到以下错误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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆