ReactNative開發筆記(持續更新...)

本文均爲RN開發過程當中遇到的問題、坑點的分析及解決方案,各問題點之間無關聯,但願能幫助讀者少走彎路,持續更新中... (2019年3月29日更新)html

原文連接:www.kovli.com/2018/06/25/…java

做者:Kovlireact

- 如何在原生端(iOS和android兩個平臺)使用ReactNative裏的本地圖片(路徑相似require('./xxximage.png'))。

在ReactNative開發過程當中,有時須要在原生端顯示RN裏的圖片,這樣的好處是能夠經過熱更新來更新APP裏的圖片,而不須要發佈原生版本,而ReactNative裏圖片路徑是相對路徑,相似'./xxximage.png'的寫法,原生端是沒法解析這類路徑,那麼若是將RN的圖片傳遞給原生端呢?android

解決方案ios

一、圖片若是用網絡圖,那隻須要將url字符串地址傳遞給原生便可,這種作法須要時間和網絡環境加載圖片,不屬於本地圖片,不是本方案所追求的最佳方式。git

二、懶人作法是把RN的本地圖片生成base64字符串而後傳遞給原生再解析,這種作法若是圖片太大,字符串會至關長,一樣不認爲是最佳方案。github

其實RN提供了相關的解決方法,以下:算法

RN端npm

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

複製代碼

iOS端json

#import <React/RCTConvert.h>


RCT_EXPORT_METHOD(showRNImage:(id)rnImageData){
    dispatch_async(dispatch_get_main_queue(), ^{
    UIImage *rnImage = [RCTConvert UIImage:rnImageData];
    ...
    });
}

複製代碼

安卓端

第一步,從橋接文件獲取到uri地址

@ReactMethod
public static void showRNImage(Activity activity, ReadableMap params){
     String rnImageUri;
     try {
        //圖片地址
        rnImageUri = params.getString("uri");
        Log.i("Jumping", "uri : " + uri);
        
        ...

        } catch (Exception e) {
            return;
        }
 }
 
複製代碼

第二步,建立JsDevImageLoader.java

package com.XXX;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.util.Log;


import com.XXX.NavigationApplication;

import java.io.IOException;
import java.net.URL;

public class JsDevImageLoader {
   private static final String TAG = "JsDevImageLoader";
   public static Drawable loadIcon(String iconDevUri) {
       try {
           StrictMode.ThreadPolicy threadPolicy = StrictMode.getThreadPolicy();
           StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());

           Drawable drawable = tryLoadIcon(iconDevUri);

           StrictMode.setThreadPolicy(threadPolicy);
           return drawable;
       } catch (Exception e) {
           Log.e(TAG, "Unable to load icon: " + iconDevUri);
           return new BitmapDrawable();
       }
   }

   @NonNull
   private static Drawable tryLoadIcon(String iconDevUri) throws IOException {
       URL url = new URL(iconDevUri);
       Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());
       return new BitmapDrawable(NavigationApplication.instance.getResources(), bitmap);
   }
}
複製代碼

第三步,導入ResourceDrawableIdHelper.java

package com.xg.navigation.react;// Copyright 2004-present Facebook. All Rights Reserved.

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;

import com.facebook.common.util.UriUtil;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;

/**
 * Direct copy paste from react-native, because they made that class package scope. -_-" * Can be deleted in react-native ^0.29 */ public class ResourceDrawableIdHelper { public static final ResourceDrawableIdHelper instance = new ResourceDrawableIdHelper(); private Map<String, Integer> mResourceDrawableIdMap; public ResourceDrawableIdHelper() { mResourceDrawableIdMap = new HashMap<>(); } public int getResourceDrawableId(Context context, @Nullable String name) { if (name == null || name.isEmpty()) { return 0; } name = name.toLowerCase().replace("-", "_"); if (mResourceDrawableIdMap.containsKey(name)) { return mResourceDrawableIdMap.get(name); } int id = context.getResources().getIdentifier( name, "drawable", context.getPackageName()); mResourceDrawableIdMap.put(name, id); return id; } @Nullable public Drawable getResourceDrawable(Context context, @Nullable String name) { int resId = getResourceDrawableId(context, name); return resId > 0 ? context.getResources().getDrawable(resId) : null; } public Uri getResourceDrawableUri(Context context, @Nullable String name) { int resId = getResourceDrawableId(context, name); return resId > 0 ? new Uri.Builder() .scheme(UriUtil.LOCAL_RESOURCE_SCHEME) .path(String.valueOf(resId)) .build() : Uri.EMPTY; } } 複製代碼

第四步,建立BitmapUtil.java

package com.XXX;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.MediaStore;
import android.text.TextUtils;

import com.XXX.NavigationApplication;
import com.XXX.JsDevImageLoader;
import com.XXX.ResourceDrawableIdHelper;

import java.io.IOException;


public class BitmapUtil {

    private static final String FILE_SCHEME = "file";

    public static Drawable loadImage(String iconSource) {

        if (TextUtils.isEmpty(iconSource)) {
            return null;
        }

        if (NavigationApplication.instance.isDebug()) {
            return JsDevImageLoader.loadIcon(iconSource);
        } else {
            Uri uri = Uri.parse(iconSource);
            if (isLocalFile(uri)) {
                return loadFile(uri);
            } else {
                return loadResource(iconSource);
            }
        }
    }

    private static boolean isLocalFile(Uri uri) {
        return FILE_SCHEME.equals(uri.getScheme());
    }

    private static Drawable loadFile(Uri uri) {
        Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath());
        return new BitmapDrawable(NavigationApplication.instance.getResources(), bitmap);
    }

    private static Drawable loadResource(String iconSource) {
        return ResourceDrawableIdHelper.instance.getResourceDrawable(NavigationApplication.instance, iconSource);
    }

    public static Bitmap getBitmap(Activity activity, String uri) {

        if (activity == null || uri == null || TextUtils.isEmpty(uri)) {
            return null;
        }

        Uri mImageCaptureUri;
        try {
            mImageCaptureUri = Uri.parse(uri);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        if (mImageCaptureUri == null) {
            return null;
        }

        Bitmap bitmap = null;
        try {
            bitmap = MediaStore.Images.Media.getBitmap(activity.getContentResolver(), mImageCaptureUri);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return bitmap;
    }
}

複製代碼

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

...
BitmapUtil.loadImage(rnImageUri)
...

複製代碼

第六步,顯示圖片

import android.widget.RelativeLayout;
import android.support.v7.widget.AppCompatImageView;
import android.graphics.drawable.Drawable;

...
final RelativeLayout item = (RelativeLayout) mBottomBar.getChildAt(i);
final AppCompatImageView itemIcon = (AppCompatImageView) item.getChildAt(0);
itemIcon.setImageDrawable(BitmapUtil.loadImage(rnImageUri));

...



複製代碼

- 升級舊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:

{
  "presets": ["react-native"],
  "plugins": ["transform-decorators-legacy"]
}
To this:

{
  "presets": [
    "module:metro-react-native-babel-preset",
    "@babel/preset-flow"
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy" : true }]
  ]
}

複製代碼

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,以免被遮擋。

解決方案:參考以下例子

<ScrollView style={styles.container}>
        <KeyboardAvoidingView behavior="position" keyboardVerticalOffset={64}>
          ...
          <TextInput />
          ...
        </KeyboardAvoidingView>
      </ScrollView>


複製代碼

- ReactNative輸入框TextInput點擊彈起鍵盤,而後點擊其餘子組件,例如點擊提交按鈕,會先把鍵盤收起,再次點擊提交按鈕才響應提交按鈕,得點擊兩次,如何作到點擊提交按鈕的同時收起鍵盤並響應按鈕?

這個問題關鍵在ScrollViewkeyboardShouldPersistTaps屬性 ,首先TextInput的特殊性(有鍵盤彈起)決定了其最好包裹在ScrollView裏,其次若是當前界面有軟鍵盤,那麼點擊scrollview後是否收起鍵盤,取決於keyboardShouldPersistTaps屬性的設置。(譯註:不少人反應TextInput沒法自動失去焦點/須要點擊屢次切換到其餘組件等等問題,其關鍵都是須要將TextInput放到ScrollView中再設置本屬性)

  • 'never'(默認值),點擊TextInput之外的子組件會使當前的軟鍵盤收起。此時子元素不會收到點擊事件。
  • 'always',鍵盤不會自動收起,ScrollView也不會捕捉點擊事件,但子組件能夠捕獲。
  • 'handled',當點擊事件被子組件捕獲時,鍵盤不會自動收起。這樣切換TextInput時鍵盤能夠保持狀態。多數帶有TextInput的狀況下你應該選擇此項。
  • false,已過時,請使用'never'代替。
  • true,已過時,請使用'always'代替。

解決方案:看以下例子

<ScrollView style={styles.container}
                  keyboardShouldPersistTaps="handled">
        <TextInput />
       ...
      </ScrollView>

    //按鈕點擊事件注意收起鍵盤
      _checkAndSubmit = () => {
        Keyboard.dismiss();
      };
複製代碼

- ReactNative本地圖片如何獲取其base64編碼?(通常指採用<Image source={require('./icon.png'.../>這類相對路徑地址的圖片資源如何獲取到絕對路徑)

關鍵是要獲取到本地圖片的uri,用到了Image.resolveAssetSource方法,ImageEditor.cropImage方法和ImageStore.getBase64ForTag方法,具體能夠查詢官方文檔

解決方案:看以下代碼

import item from '../../images/avator_upload_icon.png';

      const info = Image.resolveAssetSource(item);

      ImageEditor.cropImage(info.uri, {
        size: {
          width: 126,
          height: 126
        },
        resizeMode: 'cover'
      }, uri => {
        ImageStore.getBase64ForTag(uri, base64ImageData => {
          // 獲取圖片字節碼的base64字符串
          this.setState({
            avatarBase64: base64ImageData
          });
        }, err => {
          console.warn("ImageStoreError" + JSON.stringify(err));
        });
      }, err => {
        console.warn("ImageEditorError" + JSON.stringify(err));

      });

複製代碼

- ReactNative如何讀取iOS沙盒裏的圖片?

解決方案:看以下代碼

let RNFS = require('react-native-fs');
        <Image
          style={{width:100, height:100}}
          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]
//前往更新js包
RCT_EXPORT_METHOD(gotoUpdateJS:(NSString *)jsUrl andResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
  if (!jsUrl) {
    return;
  }
  
  //jsbundle更新採用靜默更新
  //更新
  NSLog(@"jsbundleUrl is : %@",  jsUrl);
  [[LJFileHelper shared] downloadFileWithURLString:jsUrl finish:^(NSInteger status, id data) {
    if(status == 1){
      NSLog(@"下載完成");
      NSError *error;
      NSString *filePath = (NSString *)data;
      NSString *desPath = [NSString stringWithFormat:@"%@",NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]];
      [SSZipArchive unzipFileAtPath:filePath toDestination:desPath overwrite:YES password:nil error:&error];
      if(!error){
        [_bridge reload];

        resolve([NSNumber numberWithBool:true]);
        NSLog(@"解壓成功");
        
      }else{
        resolve([NSNumber numberWithBool:false]);
        NSLog(@"解壓失敗");
      }
    }
  }];

  reject = nil;
}

複製代碼
  1. JS端
// 原生端經過回調結果通知JS熱更新狀況,JS端
UpdateModule.gotoUpdateJS(jsUrl).then(resp => {

    if ( resp ) {
       // 成功更新通知隱藏啓動頁
       DeviceEventEmitter.emit("hide_loading_page",'hide');
    } else {
       // 出問題也要隱藏啓動頁,用戶繼續使用舊版本
       DeviceEventEmitter.emit("hide_loading_page",'hide');
       // 其餘處理
    }

});
複製代碼
  1. 啓動頁消失,用戶看到的是新版APP
async componentWillMount() {

        this.subscription = DeviceEventEmitter.addListener("hide_loading_page", this.hideLoadingPage);
        appUpdateModule.updateJs();


    }

    hideLoadingPage = ()=> {
        SplashScreen.hide();
    };

複製代碼

注意作好容錯,例如弱網無網環境下的處理,熱更新失敗下次保證再次熱更新的處理,熱更新時間把控,超過期間下次再reload,是否將熱更新reload權利交給用戶等等均可以擴展。

- ReactNative如何取消部分警告

debug模式下調試常常會有黃色的警告,有些警告多是短期不須要處理,經過下面的解決方法能忽略部分警告提示

解決方案:使用console.ignoredYellowBox

import { AppRegistry } from 'react-native';
import './app/Common/SetTheme'
import './app/Common/Global'


import App from './App';

console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please use BackHandler instead.',
    'source.uri should not be an empty string','Remote debugger is in a background tab which',
    'Setting a timer',
    'Encountered two children with the same key,',
    'Attempt to read an array index',
];

AppRegistry.registerComponent('ReactNativeTemplate', () => App);
複製代碼

- ReactNative開發遇到android網絡圖片顯示不出來的問題

開發過程當中有時會遇到iOS圖片正常顯示,可是安卓卻只能顯示部分網絡圖片,形成這個的緣由有多種,參考下面的解決方案。

解決方案

  1. 安卓增長resizeMethod屬性並設置爲resize
<Image style={styles.imageStyle} source={{uri: itemInfo.imageUrl || ''}} resizeMethod={'resize'}/>
複製代碼

resizeMethod官方解釋

resizeMethod  enum('auto', 'resize', 'scale') 

當圖片實際尺寸和容器樣式尺寸不一致時,決定以怎樣的策略來調整圖片的尺寸。默認值爲auto。

auto:使用啓發式算法來在resize和scale中自動決定。

resize: 在圖片解碼以前,使用軟件算法對其在內存中的數據進行修改。當圖片尺寸比容器尺寸大得多時,應該優先使用此選項。

scale:對圖片進行縮放。和resize相比, scale速度更快(通常有硬件加速),並且圖片質量更優。在圖片尺寸比容器尺寸小或者只是稍大一點時,應該優先使用此選項。

關於resize和scale的詳細說明請參考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及以上版本)
this.queryConfig();


    queryConfig = ()=> {
        this.listener = NetInfo.addEventListener('connectionChange', this._netChange);
    };
    
        // 網絡發生變化時
    _netChange = async(info)=> {
        const {
            type,
            //effectiveType
        } = info;
        const netCanUse = !(type === 'none' || type === 'unknown' || type === 'UNKNOWN' || type === 'NONE');
        if (!netCanUse) {
            this.setState({
                isNetError : true
            });
            this.alertNetError(); //或者其餘通知形式

        } else {
            try {
                // 注意這裏的await語句,其所在的函數必須有async關鍵字聲明
                let response = await fetch(CONFIG_URL);
                let responseJson = await response.json();
                const configData = responseJson.result;
                if (response && configData) {
                    this.setState({
                        is_show_tip: configData.is_show_tip,
                        app_bg: CONFIG_HOST + configData.app_bg,
                        jumpUrl: configData.url,
                        isGetConfigData: true
                    }, () => {
                        SplashScreen.hide();
                    })
                } else {
                    // 錯誤碼也去殼
                    if ( responseJson.code === 400 ) {
                        this.setState({
                            isGetConfigData: true
                        }, () => {
                            SplashScreen.hide();
                        })
                    } else {
                        this.setState({
                            isGetConfigData: false
                        }, () => {
                            SplashScreen.hide();
                        })
                    }
                }

            } catch (error) {
                console.log('queryConfig error:' + error);
                this.setState({
                    isGetConfigData: true
                }, () => {
                    SplashScreen.hide();
                })
            }

        }
    };
    
    
    
    
        alertNetError = () => {
        setTimeout(()=> {
            SplashScreen.hide();

        }, 1000);

        if ( ! this.state.is_show_tip &&  this.state.isGetConfigData ) {
            return
        } else {
            Alert.alert(
                'NetworkDisconnected',
                '',
                [
                    {text: 'NetworkDisconnected_OK', onPress: () => {
                        this.checkNetState();
                    }},
                ],
                {cancelable: false}
            );        }


    };
    
    
    
    
        checkNetState = () => {
        NetInfo.isConnected.fetch().done((isConnected) => {
            if ( !isConnected ) {
                this.alertNetError();
            } else {
                this.queryConfig();
            }
        });

    };

複製代碼
  1. 老版本
async componentWillMount() {
        this.queryConfig();
    }

    checkNetState = () => {
        NetInfo.isConnected.fetch().done((isConnected) => {
            console.log('111Then, is ' + (isConnected ? 'online' : 'offline'));
            if (!isConnected) {
                this.alertNetError();
            } else {
                this.queryConfig();
            }
        });

    };

    alertNetError = () => {
        setTimeout(()=> {
            SplashScreen.hide();

        }, 1000);
        console.log('111111');

        if (!this.state.is_show_tip && this.state.isGetConfigData) {
            console.log('222222');

            return
        } else {
            console.log('33333');

            Alert.alert(
                'NetworkDisconnected',
                '',
                [
                    {
                        text: 'NetworkDisconnected_OK', onPress: () => {
                        this.checkNetState();
                    }
                    },
                ],
                {cancelable: false}
            );
        }


    };


    queryConfig = ()=> {
       
        NetInfo.isConnected.addEventListener(
            'connectionChange',
            this._netChange
        );

    };


    // 網絡發生變化時
    _netChange = async(isConnected)=> {
        console.log('Then, is ' + (isConnected ? 'online' : 'offline'));

    
        if (!isConnected) {
            console.log('666');

            this.setState({
                isNetError: true
            });
            this.alertNetError();

        } else {
            try {
                // 注意這裏的await語句,其所在的函數必須有async關鍵字聲明
                let response = await fetch(CONFIG_URL);
                let responseJson = await response.json();
                const configData = responseJson.result;
                if (response && configData) {
                    this.setState({
                        is_show_tip: configData.is_show_tip,
                        app_bg: CONFIG_HOST + configData.app_bg,
                        jumpUrl: configData.url,
                        isGetConfigData: true
                    }, () => {
                        SplashScreen.hide();
                        this.componentNext();
                    })
                } else {
                    this.setState({
                        isGetConfigData: false
                    }, () => {
                        SplashScreen.hide();
                        this.componentNext();
                    })
                }

            } catch (error) {
                console.log('queryConfig error:' + error);
                this.setState({
                    isGetConfigData: true
                }, () => {
                    SplashScreen.hide();
                    this.componentNext();
                })
            }

        }
    };
複製代碼

- ReactNative版本升級後報錯有廢棄代碼的快速解決方法

使用第三方庫或者老版本升級時會遇到報錯提示某些方法被廢棄,這時候尋找和替換要花很多時間,並且還容易漏掉。

解決方案: 根據報錯信息,搜索廢棄的代碼,例如

報錯提示:Use viewPropTypes instead of View.propTypes.

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

替換搜索出來的代碼便可。

這是用於查找項目裏的錯誤或者被廢棄的代碼的好方法

- 解決ReactNative的TextInput在0.55中文沒法輸入的問題

此問題主要體如今iOS中文輸入法沒法輸入漢字,是0.55版RN的一個bug

解決方案:使用下面的MyTextInput替換原TextInput

import React from 'react';
import { TextInput as Input } from 'react-native';

export default class MyTextInput extends React.Component {
    static defaultProps = {
        onFocus: () => { },
    };

    constructor(props) {
        super(props);

        this.state = {
            value: this.props.value,
            refresh: false,
        };
    }

    shouldComponentUpdate(nextProps, nextState) {
        if (this.state.value !== nextState.value) {
            return false;
        }

        return true;
    }

    componentDidUpdate(prevProps) {
        if (prevProps.value !== this.props.value && this.props.value === '') {
            this.setState({ value: '', refresh: true }, () => this.setState({ refresh: false }));
        }
    }

    focus = (e) => {
        this.input.focus();
    };

    onFocus = (e) => {
        this.input.focus();

        this.props.onFocus();
    };

    render() {
        if (this.state.refresh) {
            return null;
        }

        return (
            <Input
                {...this.props}
                ref={(ref) => { this.input = ref; }}
                value={this.state.value}
                onFocus={this.onFocus}
            />
        );
    }
}
複製代碼

ReactNative集成第三方DEMO編譯時遇到RCTSRWebSocket錯誤的解決方法

報錯信息以下

Ignoring return value of function declared with warn_unused_result attribute
複製代碼

解決方案

StackOverFlow上的解決方法:

在navigator雙擊RCTWebSocket project,移除build settings > custom compiler 下的flags
複製代碼

版權聲明:

轉載時請註明做者Kovli以及本文地址: www.kovli.com/2018/06/25/…

相關文章
相關標籤/搜索