首页 > 技术文章 > React Native从0.39.x升级到0.49.x的那些事

yz1311 2017-11-24 10:24 原文

前言:

由于公司的RN的版本(v0.39.4)太老了,所以打算升级到最新的版本(0.49.3)(其实是为了使用FlatList等一些新特性及减少框架带来的bug),由于中间的版本跨度太大,所以特地记录下升级的一些要点,有一些是框架本身跟,还有一些是第三方库引起的

注意:

      1.目前是以0.49.x版本为准,如果是低于这个版本,可能有些错误并不会出现

      2.下面的问题有一些是警告,我也一并修复了,因为这些警告在后面的版本可能就会变成错误

 

1.android下GIF图片不显示(没有动画)

在android/app/build.gradle中更新freso对应的gif动画库的版本(看API最好还是看英文官网,中文网的更新不及时)

dependencies {
    ...
    compile 'com.facebook.fresco:animated-gif:0.13.0'  //需要从0.13.0升级到1.3.0
}

 

2.View.propTypes引起的错误

在RN0.44版本中,将View中的propTypes移动作为一个新的ViewPropTypes属性

  ● Move View.propTypes to ViewPropTypes (53905a5) - @bvaughn

注意:该问题在debug模式下可以运行(chrome里面console会显示错误),但是可以运行,release模式下直接报错,所以必须修改

修改方式:

import {
  Dimensions,
  PanResponder,
  NativeModules,
  StyleSheet,
  TVEventHandler,
  View,
  ViewPropTypes,
} from 'react-native';

//然后将prop定义的View.propType的地方替换成ViewPropTypes

 

3.React16引起的相关问题

https://zhuanlan.zhihu.com/p/26250968?group_id=834155723037487104

主要有两处

  •     将React库中的createClass方法移到一个独立的包 create-react-class
  • import createReactClass from 'create-react-class';
    
    var Component = createReactClass({
    
    })

       废弃了React的PropTypes,将之移到一个独立的prop-types包中

  • import PropTypes from 'prop-types';
    
    Component.propTypes = {
      text: PropTypes.string.isRequired,
    };


4.NetInfo的api变化了

在0.48.x版本中,NetInfo的API发生了变化(旧方式依旧兼容,但是会报警告),新的API解决了两个方面的问题

主要的目的是为了统一前面的字段(以前的版本iOS和android返回的信息是不一致的),并且现在能够识别2G 3G 4G
老版本的代码可以不用变化

  - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android.
  - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g.

具体查看:
https://github.com/facebook/react-native/commit/fc38fe1736080215e3c462e25081d530a5399dc3
 
 

5.zIndex问题

最新的版本是没有该问题的,在0.45.x->0.47.x, android下的zIndex是无效的,0.48.x修复了该问题
https://github.com/facebook/react-native/issues/15713
 

6.require() must have a single string literal argument" when bundling moment.js 

因为动态引用的原因,在新版本中会出现不兼容的情况,目前出现的主要有两个库realm和moment

https://github.com/facebook/react-native/issues/16216

其中moment库很快就修复了该问题

Fixed in moment 2.19.0, working for me with RN 0.49.3.
https://github.com/moment/moment/blob/develop/CHANGELOG.md

 

7.Touchable*直接作为容器引起的布局混乱

<TouchableOpacity
    activeOpacity={0.75}
    style={[styles.machineSection, { borderColor: wrapperBorderColor,flexDirection:'row',alignItems:'center',justifyContent:"space-between",paddingVertical:5,paddingLeft:5,backgroundColor:'#FAFCFF',marginTop:10,borderTopWidth:gScreen.onePix}]}
    onPress={this.selectAll.bind(this,sectionId,data)}
>
    <View style={{flexDirection:'row',alignItems:'center',backgroundColor:'green'}}>
        <Image
            style={{width:25,height:25,borderRadius:12.5,marginRight:5}}
            source={avatar}
        />
        <Text style={{color:gColors.color666,fontSize:gFont.size13}}>{data.userId===gUserData.Id?'自营':(data.group_name+' 的机器')}</Text>
    </View>
    <TouchableOpacity activeOpacity={activeOpacity}
                      style={{alignSelf:'stretch',justifyContent:'center'}}
                      onPress={this.selectAll.bind(this,sectionId,data)}
    >
        <Image
            style={{width:17,height:17,marginRight:10}}
            source={data.isSelected? require('../../../../resources/ico/slider_selected.png') : require('../../../../resources/ico/slider_blank.png')}
            resizeMode="contain"
        />
    </TouchableOpacity>
</TouchableOpacity>


不要在将TouchableOpacity直接作为容器,需要放一个子容器包着

8.Image作为容器

在rn版本0.46版本的时候添加了ImageBackground控件,在0.46版本以后使用Image的时候不能在嵌套使用,ImageBackground就是解决这个问题的,现在如果在 标签中嵌套其他组件现在会报黄盒警告。ImageBackground的使用和Image一样,只不过可以嵌套其他组件了。
在0.50.0版本中,必须要不能Image直接嵌套
 

9.PermissionAndroid的api变化了

由PermissionsAndroid.requestPermission 变为 PermissionsAndroid.request

 

10.FlatList中的extraData

前面一直没有使用,也不明白这个值到底是干什么的,直到将一个场景的ListView升级为FlatList的时候遇到问题,

 

场景是点击右上角按钮,item中的箭头会变成一个圆圈,表示可以选中

通过this,state.removeMode控制是否处于编辑模式,点击右上角按钮会将removeMode设为true

这个在ListView中是没问题的,但是在FlatList中发现,renderItem方法(没有单独写一个component,只是一个方法)没有被重新触发,最后通过查找FlatList的代码发现

class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {

FlatList是直接继承PureComponent,this.state.removeMode并没有作为FlatList的一个属性,所以其改变并不会造成FlatList的重新渲染,此时需要设置extraData={this.state.removeMode},这样才能其效果

 /**
   * A marker property for telling the list to re-render (since it implements `PureComponent`). If
   * any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the
   * `data` prop, stick it here and treat it immutably.
   */
  extraData?: any,

 

推荐阅读