Javascript this.setState 不是函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33381756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 15:00:26  来源:igfitidea点击:

this.setState is not a function

javascriptreactjsecmascript-6

提问by RRP

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?

我有以下组件,它维护在特定元素上触发事件时更新的状态,并且当状态更新时,它作为道具传递给另一个组件。我目前正在尝试为什么我收到以下错误“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:I just realized the context gets changed when "onreadyStateChange" function, so i did the following in searchGif

编辑:我刚刚意识到当“onreadyStateChange”函数时上下文发生了变化,所以我在 searchGif 中做了以下操作

searchGif(){
   //other logic
   var self = this;
   xhr.onreadystatechange = function(){
    //ajax logic
    self.setState({results: repsonse});
   }
}

回答by John Ruddell

You are losing the React class thiscontext. Bind it, and also bind it in the async callback function too.

您正在丢失 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();
    }
}

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.

箭头函数很棒的一点是它们为你绑定了你的上下文,而且语法也很棒。缺点是浏览器支持。确保您有一个 polyfil 或编译过程将其编译为 ES5 语法以实现跨浏览器性能。

If you cant do either of those then just make a shadow variable of your this context outside of the async onreadystatechangefunction and use it instead of this.

如果您不能执行其中任何一个,那么只需在异步onreadystatechange函数之外创建您的 this 上下文的影子变量,并使用它代替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

现在大多数编译器都使用箭头来处理类的绑定方法(不指定 babel 转换......等),你也可以在没有构造函数的情况下以这种方式分配状态

export default class SearchBox extends Component {
  state = { 
    results: []
  }

  searchGif = (event) => {
    // ... code here
    xhr.onreadystatechange = () => {
    // ... code here
        this.setState();
    }
  }
  render() {
    // ...
  }
}