React Native: this.setState is not a function

匿名 (未验证) 提交于 2019-12-03 02:51:02

问题:

I see a number of questions on here relating to this same issue, but it seems none match the issue I'm having, and are a bit more complex.

I am in the process of learning ReactJS and React Native. I'm in the midst of reading and following the code examples from "Learning React Native" book here: https://github.com/bonniee/learning-react-native

For some reason, calling this.setState in the code below when the handleTextChange function is called, causes the "this.SetState is not a function." error. My question is why? Unlike other questions about this same issue, I don't believe my call to this.stateState is buried in a callback function or if statement. Why is it undefined?

Here is my code:

class WeatherProject extends Component {   constructor(props) {     super(props);     this.state = {       zip: "",       forecast: null     };   }    _handleTextChange(event) {     this.setState({zip: event.nativeEvent.text});   }      render() {     return (       <View style={styles.container}>       <Text style={styles.welcome}>       You input {this.state.zip}.       </Text>       <TextInput       style={styles.input}       onSubmitEditing={this._handleTextChange}/>       </View>     );   } } 

回答1:

Do not use bind inside a render. bind is a rather expensive operation and should only happen once. you have two options:

either bind the function in the constructor:

this._handleTextChange = this._handleTextChange.bind(this); 

or use arrow function:

onSubmitEditing={(e) => this._handleTextChange(e)} /> 

Edit

Apparently arrow functions inside render is also a bad practice (Thx to Adam Terlson in the comments and answer below). You can read eslint docs which states:

A bind call or arrow function in a JSX prop will create a brand new function on every single render. This is bad for performance, as it will result in the garbage collector being invoked way more than is necessary.

Using arrow functions is obviously not as bad as using bind, but nevertheless should be avoided.



回答2:

The issue is context binding, as identified in the other comments and answers here.

However, the performance of bind itself is a non-issue. The way-more-relevant issue is that using bind or arrows in your render methods creates a new function on each render, resulting in a change of props for the child that receives them, forcing a re-render.

You have two viable options:

class WeatherProject extends Component {   constructor(props) {     super(props);      this._handleTextChange = this._handleTextChange.bind(this);   }   // ... } 

Or you can use the class property notation and assign arrow functions if you're using the babel plugin for it.

class WeatherProject extends Component {   constructor(props) {     super(props);     // ...   }    handleTextChange = (event) => {     this.setState({zip: event.nativeEvent.text});   }   // ... } 

I strongly recommend you use the eslint package with the react recommended rules enabled. It will catch errors like using bind/arrows in your render, as well as tell you that underscore prefixed functions are ugly and totally not necessary in React. :)



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!