本文均为RN开发过程中遇到的问题、坑点的分析及解决方案,各问题点之间无关联,希望能帮助读者少走弯路,持续更新中... (2019年3月29日更新)

原文链接:http://www.kovli.com/2018/06/25/rn-anything/

作者:Kovli

- 如何在原生端(iOS和android两个平台)使用ReactNative里的本地图片(路径类似require('./xxximage.png'))。

在ReactNative开发过程中,有时需要在原生端显示RN里的图片,这样的好处是可以通过热更新来更新APP里的图片,而不需要发布原生版本,而ReactNative里图片路径是相对路径,类似'./xxximage.png'的写法,原生端是无法解析这类路径,那么如果将RN的图片传递给原生端呢?

解决方案

1、图片如果用网络图,那只需要将url字符串地址传递给原生即可,这种做法需要时间和网络环境加载图片,不属于本地图片,不是本方案所追求的最佳方式。

2、懒人做法是把RN的本地图片生成base64字符串然后传递给原生再解析,这种做法如果图片太大,字符串会相当长,同样不认为是最佳方案。

其实RN提供了相关的解决方法,如下:

RN端

  1. const myImage = require('./my-image.png');
  2. const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource');
  3. const resolvedImage = resolveAssetSource(myImage);
  4. NativeModules.NativeBridge.showRNImage(resolvedImage);

iOS端

  1. #import <React/RCTConvert.h>
  2. RCT_EXPORT_METHOD(showRNImage:(id)rnImageData){
  3. dispatch_async(dispatch_get_main_queue(), ^{
  4. UIImage *rnImage = [RCTConvert UIImage:rnImageData];
  5. ...
  6. });
  7. }

安卓端

第一步,从桥接文件获取到uri地址


  1. @ReactMethod
  2. public static void showRNImage(Activity activity, ReadableMap params){
  3. String rnImageUri;
  4. try {
  5. //图片地址
  6. rnImageUri = params.getString("uri");
  7. Log.i("Jumping", "uri : " + uri);
  8. ...
  9. } catch (Exception e) {
  10. return;
  11. }
  12. }

第二步,创建JsDevImageLoader.java

  1. package com.XXX;
  2. import android.content.res.Resources;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.drawable.BitmapDrawable;
  6. import android.graphics.drawable.Drawable;
  7. import android.os.StrictMode;
  8. import android.support.annotation.NonNull;
  9. import android.util.Log;
  10. import com.XXX.NavigationApplication;
  11. import java.io.IOException;
  12. import java.net.URL;
  13. public class JsDevImageLoader {
  14. private static final String TAG = "JsDevImageLoader";
  15. public static Drawable loadIcon(String iconDevUri) {
  16. try {
  17. StrictMode.ThreadPolicy threadPolicy = StrictMode.getThreadPolicy();
  18. StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
  19. Drawable drawable = tryLoadIcon(iconDevUri);
  20. StrictMode.setThreadPolicy(threadPolicy);
  21. return drawable;
  22. } catch (Exception e) {
  23. Log.e(TAG, "Unable to load icon: " + iconDevUri);
  24. return new BitmapDrawable();
  25. }
  26. }
  27. @NonNull
  28. private static Drawable tryLoadIcon(String iconDevUri) throws IOException {
  29. URL url = new URL(iconDevUri);
  30. Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());
  31. return new BitmapDrawable(NavigationApplication.instance.getResources(), bitmap);
  32. }
  33. }

第三步,导入ResourceDrawableIdHelper.java


  1. package com.xg.navigation.react;// Copyright 2004-present Facebook. All Rights Reserved.
  2. import android.content.Context;
  3. import android.graphics.drawable.Drawable;
  4. import android.net.Uri;
  5. import com.facebook.common.util.UriUtil;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. import javax.annotation.Nullable;
  9. /**
  10. * Direct copy paste from react-native, because they made that class package scope. -_-"
  11. * Can be deleted in react-native ^0.29
  12. */
  13. public class ResourceDrawableIdHelper {
  14. public static final ResourceDrawableIdHelper instance = new ResourceDrawableIdHelper();
  15. private Map<String, Integer> mResourceDrawableIdMap;
  16. public ResourceDrawableIdHelper() {
  17. mResourceDrawableIdMap = new HashMap<>();
  18. }
  19. public int getResourceDrawableId(Context context, @Nullable String name) {
  20. if (name == null || name.isEmpty()) {
  21. return 0;
  22. }
  23. name = name.toLowerCase().replace("-", "_");
  24. if (mResourceDrawableIdMap.containsKey(name)) {
  25. return mResourceDrawableIdMap.get(name);
  26. }
  27. int id = context.getResources().getIdentifier(
  28. name,
  29. "drawable",
  30. context.getPackageName());
  31. mResourceDrawableIdMap.put(name, id);
  32. return id;
  33. }
  34. @Nullable
  35. public Drawable getResourceDrawable(Context context, @Nullable String name) {
  36. int resId = getResourceDrawableId(context, name);
  37. return resId > 0 ? context.getResources().getDrawable(resId) : null;
  38. }
  39. public Uri getResourceDrawableUri(Context context, @Nullable String name) {
  40. int resId = getResourceDrawableId(context, name);
  41. return resId > 0 ? new Uri.Builder()
  42. .scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
  43. .path(String.valueOf(resId))
  44. .build() : Uri.EMPTY;
  45. }
  46. }

第四步,创建BitmapUtil.java


  1. package com.XXX;
  2. import android.app.Activity;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.drawable.BitmapDrawable;
  6. import android.graphics.drawable.Drawable;
  7. import android.net.Uri;
  8. import android.provider.MediaStore;
  9. import android.text.TextUtils;
  10. import com.XXX.NavigationApplication;
  11. import com.XXX.JsDevImageLoader;
  12. import com.XXX.ResourceDrawableIdHelper;
  13. import java.io.IOException;
  14. public class BitmapUtil {
  15. private static final String FILE_SCHEME = "file";
  16. public static Drawable loadImage(String iconSource) {
  17. if (TextUtils.isEmpty(iconSource)) {
  18. return null;
  19. }
  20. if (NavigationApplication.instance.isDebug()) {
  21. return JsDevImageLoader.loadIcon(iconSource);
  22. } else {
  23. Uri uri = Uri.parse(iconSource);
  24. if (isLocalFile(uri)) {
  25. return loadFile(uri);
  26. } else {
  27. return loadResource(iconSource);
  28. }
  29. }
  30. }
  31. private static boolean isLocalFile(Uri uri) {
  32. return FILE_SCHEME.equals(uri.getScheme());
  33. }
  34. private static Drawable loadFile(Uri uri) {
  35. Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath());
  36. return new BitmapDrawable(NavigationApplication.instance.getResources(), bitmap);
  37. }
  38. private static Drawable loadResource(String iconSource) {
  39. return ResourceDrawableIdHelper.instance.getResourceDrawable(NavigationApplication.instance, iconSource);
  40. }
  41. public static Bitmap getBitmap(Activity activity, String uri) {
  42. if (activity == null || uri == null || TextUtils.isEmpty(uri)) {
  43. return null;
  44. }
  45. Uri mImageCaptureUri;
  46. try {
  47. mImageCaptureUri = Uri.parse(uri);
  48. } catch (Exception e) {
  49. e.printStackTrace();
  50. return null;
  51. }
  52. if (mImageCaptureUri == null) {
  53. return null;
  54. }
  55. Bitmap bitmap = null;
  56. try {
  57. bitmap = MediaStore.Images.Media.getBitmap(activity.getContentResolver(), mImageCaptureUri);
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. return null;
  61. }
  62. return bitmap;
  63. }
  64. }

第五步,使用第一步里的rnImageUri地址

  1. ...
  2. BitmapUtil.loadImage(rnImageUri)
  3. ...

第六步,显示图片


  1. import android.widget.RelativeLayout;
  2. import android.support.v7.widget.AppCompatImageView;
  3. import android.graphics.drawable.Drawable;
  4. ...
  5. final RelativeLayout item = (RelativeLayout) mBottomBar.getChildAt(i);
  6. final AppCompatImageView itemIcon = (AppCompatImageView) item.getChildAt(0);
  7. itemIcon.setImageDrawable(BitmapUtil.loadImage(rnImageUri));
  8. ...

- 升级旧RN版本到目前最新的0.57.8如果采用手动升级需要注意如下。

I upgraded from react-naitve 0.55.4 to react-native 0.57.0 and I get this error

bundling failed: Error: The 'decorators' plugin requires a 'decoratorsBeforeExport' option, whose value must be a boolean. If you are migrating from Babylon/Babel 6 or want to use the old decorators proposal, you should use the 'decorators-legacy' plugin instead of 'decorators'.

解决方案:参考如下例子

First install the new proposal decorators with npm install @babel/plugin-proposal-decorators --save-dev or yarn add @babel/plugin-proposal-decorators --dev

Then, inside of your .babelrc file, change this:

  1. {
  2. "presets": ["react-native"],
  3. "plugins": ["transform-decorators-legacy"]
  4. }
  5. To this:
  6. {
  7. "presets": [
  8. "module:metro-react-native-babel-preset",
  9. "@babel/preset-flow"
  10. ],
  11. "plugins": [
  12. ["@babel/plugin-proposal-decorators", { "legacy" : true }]
  13. ]
  14. }

EDIT:

After you've updated your .babelrc file, make sure to add preset-flow as well with the command yarn add @babel/preset-flow --dev or npm install @babel/preset-flow --save-dev

- ReactNative输入框TextInput点击弹起键盘,如果键盘遮挡了重要位置,如何让界面自动跟随键盘调整?

使用这个组件KeyboardAvoidingView

本组件用于解决一个常见的尴尬问题:手机上弹出的键盘常常会挡住当前的视图。本组件可以自动根据键盘的位置,调整自身的position或底部的padding,以避免被遮挡。

解决方案:参考如下例子

  1. <ScrollView style={styles.container}>
  2. <KeyboardAvoidingView behavior="position" keyboardVerticalOffset={64}>
  3. ...
  4. <TextInput />
  5. ...
  6. </KeyboardAvoidingView>
  7. </ScrollView>

- ReactNative输入框TextInput点击弹起键盘,然后点击其他子组件,例如点击提交按钮,会先把键盘收起,再次点击提交按钮才响应提交按钮,得点击两次,如何做到点击提交按钮的同时收起键盘并响应按钮?

这个问题关键在ScrollViewkeyboardShouldPersistTaps属性

,首先TextInput的特殊性(有键盘弹起)决定了其最好包裹在ScrollView里,其次如果当前界面有软键盘,那么点击scrollview后是否收起键盘,取决于keyboardShouldPersistTaps属性的设置。(译注:很多人反应TextInput无法自动失去焦点/需要点击多次切换到其他组件等等问题,其关键都是需要将TextInput放到ScrollView中再设置本属性)

  • 'never'(默认值),点击TextInput以外的子组件会使当前的软键盘收起。此时子元素不会收到点击事件。
  • 'always',键盘不会自动收起,ScrollView也不会捕捉点击事件,但子组件可以捕获。
  • 'handled',当点击事件被子组件捕获时,键盘不会自动收起。这样切换TextInput时键盘可以保持状态。多数带有TextInput的情况下你应该选择此项。
  • false,已过期,请使用'never'代替。
  • true,已过期,请使用'always'代替。

解决方案:看如下例子

  1. <ScrollView style={styles.container}
  2. keyboardShouldPersistTaps="handled">
  3. <TextInput />
  4. ...
  5. </ScrollView>
  6. //按钮点击事件注意收起键盘
  7. _checkAndSubmit = () => {
  8. Keyboard.dismiss();
  9. };

- ReactNative本地图片如何获取其base64编码?(一般指采用<Image source={require('./icon.png'.../>这类相对路径地址的图片资源如何获取到绝对路径)

关键是要获取到本地图片的uri,用到了Image.resolveAssetSource方法,ImageEditor.cropImage方法和ImageStore.getBase64ForTag方法,具体可以查询官方文档

解决方案:看如下代码

  1. import item from '../../images/avator_upload_icon.png';
  2. const info = Image.resolveAssetSource(item);
  3. ImageEditor.cropImage(info.uri, {
  4. size: {
  5. width: 126,
  6. height: 126
  7. },
  8. resizeMode: 'cover'
  9. }, uri => {
  10. ImageStore.getBase64ForTag(uri, base64ImageData => {
  11. // 获取图片字节码的base64字符串
  12. this.setState({
  13. avatarBase64: base64ImageData
  14. });
  15. }, err => {
  16. console.warn("ImageStoreError" + JSON.stringify(err));
  17. });
  18. }, err => {
  19. console.warn("ImageEditorError" + JSON.stringify(err));
  20. });

- ReactNative如何读取iOS沙盒里的图片?

解决方案:看如下代码

  1. let RNFS = require('react-native-fs');
  2. <Image
  3. style={{width:100, height:100}}
  4. source={{uri: 'file://' + RNFS.DocumentDirectoryPath + '/myAwesomeSubDir/my.png', scale:1}}

- ReactNative如何做到图片宽度不变,宽高保持比例,高度自动调整。

RN图片均需要指定宽高才会显示,如果图片数据的宽高不定,但又希望宽度保持不变、不同图片的高度根据比例动态变化,就需要用到下面这个库,业务场景常用于文章、商品详情的多图展示。

解决方案:使用react-native-scalable-image

- navigor 无法使用的解决办法

从0.44版本开始,Navigator被从react native的核心组件库中剥离到了一个名为react-native-deprecated-custom-components的单独模块中。如果你需要继续使用Navigator,则需要先npm i facebookarchive/react-native-custom-components安装,然后从这个模块中import,即import { Navigator } from 'react-native-deprecated-custom-components'

如果报错如下参考下面的解决方案

React-Native – undefined is not an object (“evaluating _react3.default.PropTypes.shape”)

解决方案

如果已经安装了,先卸载npm uninstall --save react-native-deprecated-custom-components

用下面的命令安装

npm install --save https://github.com/facebookarchive/react-native-custom-components.git

在我们使用Navigator的js文件中加入下面这个导入包就可以了。

import { Navigator } from'react-native-deprecated-custom-components';(注意最后有一个分号)

就可以正常使用Navigator组件了。

- ReactNative开发的APP启动闪白屏问题

由于处理JS需要时间,APP启动会出现一闪而过白屏,可以通过启动页延迟加载方法来避免这类白屏,可以用下面的库

解决方案react-native-splash-screen

- ReactNative如何做到无感热更新

无论是整包热更新还是差量热更新,均需要最终替换JSBundle等文件来完成更新过程,实现原理是js来控制启动页的消失时间,等原生把bundle包下载(或合并成新bundle包)解压到目录以后,通知js消失启动页,由于热更新时间一般很短,建议使用差量热更新,一秒左右,所以用户等启动页消失后看到的就是最新的版本。

解决方案(以整包更新为例):

  1. 原生端完成更新及刷新操作,注意里面的 [_bridge reload]
  1. //前往更新js包
  2. RCT_EXPORT_METHOD(gotoUpdateJS:(NSString *)jsUrl andResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
  3. if (!jsUrl) {
  4. return;
  5. }
  6. //jsbundle更新采用静默更新
  7. //更新
  8. NSLog(@"jsbundleUrl is : %@", jsUrl);
  9. [[LJFileHelper shared] downloadFileWithURLString:jsUrl finish:^(NSInteger status, id data) {
  10. if(status == 1){
  11. NSLog(@"下载完成");
  12. NSError *error;
  13. NSString *filePath = (NSString *)data;
  14. NSString *desPath = [NSString stringWithFormat:@"%@",NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]];
  15. [SSZipArchive unzipFileAtPath:filePath toDestination:desPath overwrite:YES password:nil error:&error];
  16. if(!error){
  17. [_bridge reload];
  18. resolve([NSNumber numberWithBool:true]);
  19. NSLog(@"解压成功");
  20. }else{
  21. resolve([NSNumber numberWithBool:false]);
  22. NSLog(@"解压失败");
  23. }
  24. }
  25. }];
  26. reject = nil;
  27. }
  1. JS端
  1. // 原生端通过回调结果通知JS热更新情况,JS端
  2. UpdateModule.gotoUpdateJS(jsUrl).then(resp => {
  3. if ( resp ) {
  4. // 成功更新通知隐藏启动页
  5. DeviceEventEmitter.emit("hide_loading_page",'hide');
  6. } else {
  7. // 出问题也要隐藏启动页,用户继续使用旧版本
  8. DeviceEventEmitter.emit("hide_loading_page",'hide');
  9. // 其他处理
  10. }
  11. });
  1. 启动页消失,用户看到的是新版APP
  1. async componentWillMount() {
  2. this.subscription = DeviceEventEmitter.addListener("hide_loading_page", this.hideLoadingPage);
  3. appUpdateModule.updateJs();
  4. }
  5. hideLoadingPage = ()=> {
  6. SplashScreen.hide();
  7. };

注意做好容错,例如弱网无网环境下的处理,热更新失败下次保证再次热更新的处理,热更新时间把控,超过时间下次再reload,是否将热更新reload权利交给用户等等都可以扩展。

- ReactNative如何取消部分警告

debug模式下调试经常会有黄色的警告,有些警告可能是短时间不需要处理,通过下面的解决方法能忽略部分警告提示

解决方案:使用console.ignoredYellowBox

  1. import { AppRegistry } from 'react-native';
  2. import './app/Common/SetTheme'
  3. import './app/Common/Global'
  4. import App from './App';
  5. console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please use BackHandler instead.',
  6. 'source.uri should not be an empty string','Remote debugger is in a background tab which',
  7. 'Setting a timer',
  8. 'Encountered two children with the same key,',
  9. 'Attempt to read an array index',
  10. ];
  11. AppRegistry.registerComponent('ReactNativeTemplate', () => App);

- ReactNative开发遇到android网络图片显示不出来的问题

开发过程中有时会遇到iOS图片正常显示,但是安卓却只能显示部分网络图片,造成这个的原因有多种,参考下面的解决方案。

解决方案

  1. 安卓增加resizeMethod属性并设置为resize
  1. <Image style={styles.imageStyle} source={{uri: itemInfo.imageUrl || ''}} resizeMethod={'resize'}/>

resizeMethod官方解释

  1. resizeMethod enum('auto', 'resize', 'scale')
  2. 当图片实际尺寸和容器样式尺寸不一致时,决定以怎样的策略来调整图片的尺寸。默认值为auto
  3. auto:使用启发式算法来在resizescale中自动决定。
  4. resize 在图片解码之前,使用软件算法对其在内存中的数据进行修改。当图片尺寸比容器尺寸大得多时,应该优先使用此选项。
  5. scale:对图片进行缩放。和resize相比, scale速度更快(一般有硬件加速),而且图片质量更优。在图片尺寸比容器尺寸小或者只是稍大一点时,应该优先使用此选项。
  6. 关于resizescale的详细说明请参考http://frescolib.org/docs/resizing-rotating.html.
  1. 如果是FlatList或ScrollView等包裹图片,尝试设置

removeClippedSubviews={true}//ios set false

  1. 如果还是有问题,尝试配合react-native-image-progress

    还可以谨慎尝试使用react-native-fast-image

- ReactNative判断及监控网络情况方法总结

提前获取用户的网络情况很有必要,RN主要靠NetInfo来获取网络状态,不过随着RN版本的更新也有一些变化。

解决方案:

  1. 较新的RN版本(大概是0.50及以上版本)
  1. this.queryConfig();
  2. queryConfig = ()=> {
  3. this.listener = NetInfo.addEventListener('connectionChange', this._netChange);
  4. };
  5. // 网络发生变化时
  6. _netChange = async(info)=> {
  7. const {
  8. type,
  9. //effectiveType
  10. } = info;
  11. const netCanUse = !(type === 'none' || type === 'unknown' || type === 'UNKNOWN' || type === 'NONE');
  12. if (!netCanUse) {
  13. this.setState({
  14. isNetError : true
  15. });
  16. this.alertNetError(); //或者其他通知形式
  17. } else {
  18. try {
  19. // 注意这里的await语句,其所在的函数必须有async关键字声明
  20. let response = await fetch(CONFIG_URL);
  21. let responseJson = await response.json();
  22. const configData = responseJson.result;
  23. if (response && configData) {
  24. this.setState({
  25. is_show_tip: configData.is_show_tip,
  26. app_bg: CONFIG_HOST + configData.app_bg,
  27. jumpUrl: configData.url,
  28. isGetConfigData: true
  29. }, () => {
  30. SplashScreen.hide();
  31. })
  32. } else {
  33. // 错误码也去壳
  34. if ( responseJson.code === 400 ) {
  35. this.setState({
  36. isGetConfigData: true
  37. }, () => {
  38. SplashScreen.hide();
  39. })
  40. } else {
  41. this.setState({
  42. isGetConfigData: false
  43. }, () => {
  44. SplashScreen.hide();
  45. })
  46. }
  47. }
  48. } catch (error) {
  49. console.log('queryConfig error:' + error);
  50. this.setState({
  51. isGetConfigData: true
  52. }, () => {
  53. SplashScreen.hide();
  54. })
  55. }
  56. }
  57. };
  58. alertNetError = () => {
  59. setTimeout(()=> {
  60. SplashScreen.hide();
  61. }, 1000);
  62. if ( ! this.state.is_show_tip && this.state.isGetConfigData ) {
  63. return
  64. } else {
  65. Alert.alert(
  66. 'NetworkDisconnected',
  67. '',
  68. [
  69. {text: 'NetworkDisconnected_OK', onPress: () => {
  70. this.checkNetState();
  71. }},
  72. ],
  73. {cancelable: false}
  74. ); }
  75. };
  76. checkNetState = () => {
  77. NetInfo.isConnected.fetch().done((isConnected) => {
  78. if ( !isConnected ) {
  79. this.alertNetError();
  80. } else {
  81. this.queryConfig();
  82. }
  83. });
  84. };
  1. 老版本
  1. async componentWillMount() {
  2. this.queryConfig();
  3. }
  4. checkNetState = () => {
  5. NetInfo.isConnected.fetch().done((isConnected) => {
  6. console.log('111Then, is ' + (isConnected ? 'online' : 'offline'));
  7. if (!isConnected) {
  8. this.alertNetError();
  9. } else {
  10. this.queryConfig();
  11. }
  12. });
  13. };
  14. alertNetError = () => {
  15. setTimeout(()=> {
  16. SplashScreen.hide();
  17. }, 1000);
  18. console.log('111111');
  19. if (!this.state.is_show_tip && this.state.isGetConfigData) {
  20. console.log('222222');
  21. return
  22. } else {
  23. console.log('33333');
  24. Alert.alert(
  25. 'NetworkDisconnected',
  26. '',
  27. [
  28. {
  29. text: 'NetworkDisconnected_OK', onPress: () => {
  30. this.checkNetState();
  31. }
  32. },
  33. ],
  34. {cancelable: false}
  35. );
  36. }
  37. };
  38. queryConfig = ()=> {
  39. NetInfo.isConnected.addEventListener(
  40. 'connectionChange',
  41. this._netChange
  42. );
  43. };
  44. // 网络发生变化时
  45. _netChange = async(isConnected)=> {
  46. console.log('Then, is ' + (isConnected ? 'online' : 'offline'));
  47. if (!isConnected) {
  48. console.log('666');
  49. this.setState({
  50. isNetError: true
  51. });
  52. this.alertNetError();
  53. } else {
  54. try {
  55. // 注意这里的await语句,其所在的函数必须有async关键字声明
  56. let response = await fetch(CONFIG_URL);
  57. let responseJson = await response.json();
  58. const configData = responseJson.result;
  59. if (response && configData) {
  60. this.setState({
  61. is_show_tip: configData.is_show_tip,
  62. app_bg: CONFIG_HOST + configData.app_bg,
  63. jumpUrl: configData.url,
  64. isGetConfigData: true
  65. }, () => {
  66. SplashScreen.hide();
  67. this.componentNext();
  68. })
  69. } else {
  70. this.setState({
  71. isGetConfigData: false
  72. }, () => {
  73. SplashScreen.hide();
  74. this.componentNext();
  75. })
  76. }
  77. } catch (error) {
  78. console.log('queryConfig error:' + error);
  79. this.setState({
  80. isGetConfigData: true
  81. }, () => {
  82. SplashScreen.hide();
  83. this.componentNext();
  84. })
  85. }
  86. }
  87. };

- ReactNative版本升级后报错有废弃代码的快速解决方法

使用第三方库或者老版本升级时会遇到报错提示某些方法被废弃,这时候寻找和替换要花不少时间,而且还容易漏掉。

解决方案

根据报错信息,搜索废弃的代码,例如

报错提示:Use viewPropTypes instead of View.propTypes.

搜索命令:grep -r 'View.propTypes' .

替换搜索出来的代码即可。

这是用于查找项目里的错误或者被废弃的代码的好方法

- 解决ReactNative的TextInput在0.55中文无法输入的问题

此问题主要体现在iOS中文输入法无法输入汉字,是0.55版RN的一个bug

解决方案:使用下面的MyTextInput替换原TextInput

  1. import React from 'react';
  2. import { TextInput as Input } from 'react-native';
  3. export default class MyTextInput extends React.Component {
  4. static defaultProps = {
  5. onFocus: () => { },
  6. };
  7. constructor(props) {
  8. super(props);
  9. this.state = {
  10. value: this.props.value,
  11. refresh: false,
  12. };
  13. }
  14. shouldComponentUpdate(nextProps, nextState) {
  15. if (this.state.value !== nextState.value) {
  16. return false;
  17. }
  18. return true;
  19. }
  20. componentDidUpdate(prevProps) {
  21. if (prevProps.value !== this.props.value && this.props.value === '') {
  22. this.setState({ value: '', refresh: true }, () => this.setState({ refresh: false }));
  23. }
  24. }
  25. focus = (e) => {
  26. this.input.focus();
  27. };
  28. onFocus = (e) => {
  29. this.input.focus();
  30. this.props.onFocus();
  31. };
  32. render() {
  33. if (this.state.refresh) {
  34. return null;
  35. }
  36. return (
  37. <Input
  38. {...this.props}
  39. ref={(ref) => { this.input = ref; }}
  40. value={this.state.value}
  41. onFocus={this.onFocus}
  42. />
  43. );
  44. }
  45. }

ReactNative集成第三方DEMO编译时遇到RCTSRWebSocket错误的解决方法

报错信息如下

  1. Ignoring return value of function declared with warn_unused_result attribute

解决方案

StackOverFlow上的解决方法:

  1. navigator双击RCTWebSocket project,移除build settings > custom compiler 下的flags

版权声明:

转载时请注明作者Kovli以及本文地址:

http://www.kovli.com/2018/06/25/rn-anything/


ReactNative开发笔记(持续更新...)的更多相关文章

  1. React-Native开发笔记 持续更新

    1.css单位转换px2dp 在做页面开发的时候习惯了用rem去做css单位,处理各种尺寸数据,到了React-Native里面做app开发时,rem就不好用了,这个时候就需要转换成另外一个单位,基本 ...

  2. BLE资料应用笔记 -- 持续更新

    BLE资料应用笔记 -- 持续更新 BLE 应用笔记 小书匠 简而言之,蓝牙无处不在,易于使用,低耗能和低使用成本.'让我们'更深入地探索这些方面吧. 蓝牙无处不在-,您可以在几乎每一台电话.笔记本电 ...

  3. [读书]10g/11g编程艺术深入体现结构学习笔记(持续更新...)

    持续更新...) 第8章 1.在过程性循环中提交更新容易产生ora-01555:snapshot too old错误.P257 (这种情况我觉得应该是在高并发的情况下才会产生) 假设的一个场景是系统一 ...

  4. react-native-storage 使用笔记 持续更新

    React-native-storage是在AsyncStorage之上封装的一个缓存操作插件库,刚开始接触这个也遇到了一些问题,在这里简单记录总结一下,碰到了就记下来,持续更新吧 1.安卓下stor ...

  5. web前端开发随手笔记 - 持续更新

    本文仅为个人常用代码整理,供自己日常查阅 html 浏览器内核 <!--[if IE]><![endif]--> <!--[if IE 6]><![endif ...

  6. webpack4搭建Vue开发环境笔记~~持续更新

    项目git地址 一.node知识 __dirname: 获取当前文件所在路径,等同于path.dirname(__filename) console.log(__dirname); // Prints ...

  7. BLE资料应用笔记 -- 持续更新(转载)

    简而言之,蓝牙无处不在,易于使用,低耗能和低使用成本.’让我们’更深入地探索这些方面吧. 蓝牙无处不在—,您可以在几乎每一台电话.笔记本电脑 .台式电脑和平板电脑中找到蓝牙.因此,您可以便利地连接键盘 ...

  8. 数据分析之Pandas和Numpy学习笔记(持续更新)<1>

    pandas and numpy notebook        最近工作交接,整理电脑资料时看到了之前的基于Jupyter学习数据分析相关模块学习笔记.想着拿出来分享一下,可是Jupyter导出来h ...

  9. react-navigation 使用笔记 持续更新中

    目录 基本使用(此处基本使用仅针对导航头部而言,不包含tabbar等) header怎么和app中通信呢? React-Navigation是目前React-Native官方推荐的导航组件,代替了原用 ...

随机推荐

  1. C++一种高精度计时器

    在windows下可以通过QueryPerformanceFrequency()和QueryPerformanceCounter()等系列函数来实现计时器的功能. 根据其函数说明,其精度能够达到微秒级 ...

  2. arcgis api 3.x for js 入门开发系列十五台风轨迹

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  3. RabbitMQ for Mac OS Install

    使用brew来安装 RabbitMQ brew install rabbitmq 执行看到如下命令: Updating Homebrew... ==> Auto-updated Homebrew ...

  4. kkkK的随笔

    自我介绍 学号:211606310 姓名:柯伟敏 爱好:篮球,足球 最爱的菜:4堂的饺子 最想说的话:一切都是最好的安排 初入大学 -------------------- 选择 选择软件工程这个专业 ...

  5. TSC条码打印机C#例程(tsclib.dll调用) 【转】

    //----  program.cs using System;using System.Collections.Generic;using System.Windows.Forms; using S ...

  6. C学习笔记(逗号表达式)

    (1)书写: ① int i; i=(i=*,i*); printf("%d\n",i); i=60; ② int i; i=i=*,i*; printf("%d\n&q ...

  7. js坚持不懈之17:onmousedown、onmouseup 以及 onclick 事件

    <!DOCTYPE html> <html> <body> <div onmouseover = "mOver(this)" onmous ...

  8. c++11の关联容器

    一.关联容器 C++的容器类型可以分为顺序容器和关联容器两大类.对于关联容器,主要有map和set,对于这两种,根据不同的维度,衍生出了8种容器 map                        ...

  9. Pyinstaller 打包exe

    安装 ​ pip insatll Pyinstaller 参数 pyinstaller -Fw main.py 参数 概述 -F,-onefile 打包一个单个文件,如果你的代码都写在一个.py文件的 ...

  10. Java 7 和 Java 8 中的 HashMap原理解析

    HashMap 可能是面试的时候必问的题目了,面试官为什么都偏爱拿这个问应聘者?因为 HashMap 它的设计结构和原理比较有意思,它既可以考初学者对 Java 集合的了解又可以深度的发现应聘者的数据 ...