react-native 之"Cannot update during an exitsting state transition" 与 函数方法bind()/箭头函数有关?

前端之家收集整理的这篇文章主要介绍了react-native 之"Cannot update during an exitsting state transition" 与 函数方法bind()/箭头函数有关?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

react-native Warning:setState(...):Cannot update during an exitsting state transition...
这个问题出现的确实让我措手不及,结果是这样的

业务逻辑:在页面HomePage中点击setting-item按钮弹出页面ThemePage,并选择自己喜欢的样式进行样式的切换。
导致错误操作:点击了js页面的一个方法onPress={this.onSelectThemeItem(key)}所导致的。即第14行代码中的方法onPress 的开始触发了问题!


代码是这样的,下面的代码是会出现上面错误代码

extends Component组件的js页面中的部分代码展示

  1. export default class xxComponent extends Component {
  2.  
  3. ...
  4. ..
  5.  
  6. onSelectThemeItem(key) {
  7. this.props.onModalClose();
  8. this.themeDao.saveTheme(ThemeFlags[key]);
  9. //发送通知通知修改主题
  10. DeviceEventEmitter.emit('ACTION_BASE',ACTION_NOTIFY.changeTheme,ThemeFactory.createTheme(ThemeFlags[key]))
  11. }
  12.  
  13. getThemeItem(key) {
  14. let themeTitle = <TouchableOpacity style={{flex: 1}} onPress={this.onSelectThemeItem(key)}>
  15. <View style={[{backgroundColor: ThemeFlags[key]},styles.themeItem]}>
  16. <Text style={{color: 'white',fontWeight: '300'}}>{key}</Text>
  17. </View>
  18. </TouchableOpacity>;
  19.  
  20. return themeTitle;
  21. }
  22.  
  23. ...
  24. ..
  25. }

而这里出现的问题:view绘制中,再次更改props,导致view会再次去render,报错!就在14行的代码..

这种问题最可能出现的位置,就是在你所触发的方法中需要创建一个匿名函数(箭头函数),而你确没能满足。
为什么?下文解决

解决问题方法
代码

换作


分析”Cannot update during an exitsting state transition” 与 函数方法bind()箭头函数的关系

从上面犯错的代码截取一段代码来看,逻辑是在一个页面中通过点击页面中的一个组件而触发一个事件。
从这行代码上看,事实确是在刚执行到该页面js代码,进行渲染的时候就会去执行花括号中的方法this.onSelectThemeItem(key) ,导致在view渲染中又请求渲染的操作。从而报以上的错误

首先了解下平时我们写bind()方法箭头函数的几种形式
第一种

  1. ...
  2. xxFunction(){..}
  3. ...
  4. <XXView xxxx={this.xxFunction.bind(this)} />

第二种

  1. constructor(props) {
  2. super(props);
  3. this.xxFunction= this.xxFunction.bind(this);
  4. }
  5.  
  6. ...
  7. xxFunction(){..}
  8. ...

第三种

  1. ...
  2. xxFunction= ()=>{..};
  3. ...
  4. <XXView xxxx={this.xxFunction} />

第四种

  1. ...
  2. xxFunction(){..}
  3. ...
  4. <XXView xxxx={()=>this.xxFunction()} />

bind函数箭头函数区别:
在ES5下,React.createClass会把所有的方法都bind一遍,这样可以提交到任意的地方作为回调函数,而this不会变化。
在ES6下,你需要通过bind来绑定this引用,或者使用箭头函数(它会绑定当前scope的this引用)来调用

由此能够得出=>>>bind()方法箭头函数在使用是等价的。且在其形式上2和3是一致的、1和4是一致的。

通过 bind() 函数会创建一个新函数(称为绑定函数),该新函数是由指定的this值和初始化参数改造的原函数拷贝。

好的,让我们一同看下代码

  1. /** * Created by YJH on 2018/6/13. */
  2. import React,{Component} from 'react';
  3. import {
  4. BackAndroid,} from 'react-native';
  5.  
  6. export default class Backforward{
  7. constructor(props){
  8. this.backpress = this.onHardwareBackforward.bind(this);
  9. this.props=props;//由于不是component组件,所以后面使用props时候,需要将props通过this.props存储起来
  10. }
  11.  
  12. componentDidMount(){
  13. if(this.props.backforward){
  14. BackAndroid.addEventListener("backforward",this.backpress);
  15. }
  16. }
  17.  
  18. componentWillUnmount(){
  19. if(this.props.backforward){
  20. BackAndroid.removeEventListener("backforward",this.backpress);
  21. }
  22. }
  23. onHardwareBackforward(e){
  24.  
  25. return this.props.backforward(e);
  26. }
  27.  
  28. }

通过bind绑定函数onHardwareBackforward返回一个原始函数拷贝的新函数this.backpress;并在17行和23行代码上使用react-native内的组件BackAndroid添加了安卓手机返回按钮的监听,和移除监听。当用户点击手机返回按钮则触发26行代码onHardwareBackforward方法执行,并调用暴露在js页面中的方法执行关闭当前的js页面

就是下面代码

  1. export default class xxDetailPage extends Component {
  2.  
  3. constructor(props) {
  4. super(props);
  5. //实现对android手机返回按钮的监听返回功能
  6. this.backforward = new Backforward({backforward: (e) => this.onBackforward(e)}); ... } componentDidMount(){ this.backforward.componentDidMount(); } componentWillUnmount(){ this.backforward.componentWillUnmount(); } onBackforward(e) { this.goBack(); return true; } goBack() { if (this.state.isBack) { this.webView.goBack(); } else { this.props.navigator.pop(); } } ... .. }

Backforward.js第28行代码调用xxDetailPage.js第16行代码,完成了回调监听!当然,这种方式使用箭头函数也是可以实现的!

参考内容
https://blog.csdn.net/sinat
https://developer.mozilla.org
http://bbs.reactnative.cn

猜你在找的React相关文章