2016-07-18 56 views
11

我在这里看到一些关于这个问题的问题,但似乎没有什么符合我遇到的问题,并且有点复杂。React Native:this.setState不是函数

我正在学习ReactJS和React Native。我在阅读之中和之后从“学习母语做出反应”一书在这里的代码示例:https://github.com/bonniee/learning-react-native

出于某种原因,呼吁this.setState在当handleTextChange函数被调用下面的代码,使“这个.SetState不是一个函数。“错误。我的问题是为什么?与关于这个问题的其他问题不同,我不相信我对this.stateState的调用被隐藏在回调函数或语句中。为什么没有定义?

这里是我的代码:

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> 
    ); 
    } 
} 
+5

'onSubmitEditing = {this._handleTextChange.bind(this)} />',或'onSubmitEditing = {()=> this。_handleTextChange()} />' –

+0

@AlexanderT。这很好,谢谢。那么,为什么我需要将它绑定到该处理程序呢? –

+0

你可以看到这篇文章:https://medium.com/@razgoldin/using-react-es-6-syntax-fc05acf72810#.rab7bgxnw – Zargold

回答

26

不要使用绑定内渲染。绑定是一个相当昂贵的操作,应该只发生一次。你有两个选择:

或者绑定功能,在构造函数中:

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

,或者使用箭头功能:

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

编辑

显然箭头函数中渲染也一个不好的做法(Thx to Adam Terlson在下面的评论和回答中)。您可以阅读eslint docs哪些状态:

JSX支持中的绑定调用或箭头函数将在每个渲染器上创建一个全新的函数。这对性能不利,因为它会导致垃圾收集器被调用的方式超过了必要的方式。

使用箭头函数显然不像使用bind那么糟糕,但应该避免。

+1

或ES7建议的功能':: this._handleTextChange' – ZekeDroid

+0

通过使用导致子组件上不必要的重新呈现的性能影响渲染函数中的箭头可能比bind函数本身的性能差一个数量级。 –

+0

我从来没有听说过这样的事情。每个教程都鼓励使用箭头函数而不是绑定。你能否提供你所说的来源? – atlanteh

5

问题是上下文绑定,正如其他评论和答案在这里所标识的。

但是,绑定本身的性能不成问题。与路径更相关的问题是,在渲染方法中使用绑定或箭头会在每个渲染上创建一个新函数,导致接收它们的子项的道具更改,从而强制重新渲染。

你有两种可行的方案:

class WeatherProject extends Component { 
    constructor(props) { 
    super(props); 

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

或者你也可以使用类属性的符号,并指定箭头的功能,如果你使用的babel plugin它。

class WeatherProject extends Component { 
    constructor(props) { 
    super(props); 
    // ... 
    } 

    handleTextChange = (event) => { 
    this.setState({zip: event.nativeEvent.text}); 
    } 
    // ... 
} 

我强烈建议您使用启用了react recommended rules的eslint软件包。它会捕获在渲染中使用绑定/箭头等错误,并告诉你下划线前缀函数在React中是丑陋和完全不必要的。 :)

+0

其实根据eslint [docs](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md),唯一的问题是创建全新的功能在每次通话中,这对性能都不利,但不会导致孩子重新呈现 – atlanteh

+0

@atlanteh是的,这是事实,但我的观点仍然有效。这只是许多文章中涉及支柱变更问题的文章之一。 https://medium.com/@esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f?source=linkShare-583b3a685d22-1481269421 –

+0

是的,这就是为什么我更新了我的答案:) – atlanteh

相关问题