我有以下组件,该组件维护在特定元素上触发事件时更新的状态,并且在更新状态时将其作为道具传递给另一个组件。我目前正在尝试为什么我得到以下错误“ 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> ); } }
编辑: 我只是意识到上下文会在“onreadyStateChange”函数时发生更改,所以我在searchGif中做了以下操作
searchGif(){ //other logic var self = this; xhr.onreadystatechange = function(){ //ajax logic self.setState({results: repsonse}); } }
您正在丢失React类this上下文。绑定它,并将其也绑定到异步回调函数中。
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(); } }
关于箭头功能的很棒的事情是它们为您绑定了上下文,并且语法也很棒。缺点是浏览器支持。确保您具有polyfil或编译过程以将其编译为ES5语法,以实现跨浏览器性能。
如果您不能执行任何一项操作,则只需在异步onreadystatechange函数外部为此上下文创建一个阴影变量,然后使用它代替即可this。
onreadystatechange
如今,大多数编译器都使用箭头处理类的绑定方法(无需指定babel转换…等),您也可以通过这种方式分配状态,而无需构造函数
export default class SearchBox extends Component { state = { results: [] } searchGif = (event) => { // ... code here xhr.onreadystatechange = () => { // ... code here this.setState(); } } render() { // ... } }