React Native问题记录

记录一些开发中遇到的问题以及解决办法。

1、ScrollView的onScroll只调用一次

其实日志中已经提示了我们
You specified onScroll on a <ScrollView> but not scrollEventThrottle . You will only receive one event. Using 16 you get all the events but be aware that it may cause frame drops, use a bigger number if you don't need as much precision.
所以解决办法就是增加scrollEventThrottle属性。
建议简单判断一下系统和机型,在低端手机上设置的值大一点,高端手机上值设置小一点,这样可以一定程度上保证流畅度。

2、Tried to register two views with the same name xxxx

原因:是多次使用requireNativeComponent同一个组件。
解决办法:检查代码,找出多次使用的代码,使用RN包装一次这个原生组件,其他地方使用这个包装后的RN组件。

3、组件库demo目录引用外层组件源码目录代码

使用以下方式依赖:
"react-navigation": "link:../.."

4、Android端崩溃,报 java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference

日志如下:

java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3408)
    at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:663)
    at android.view.View.updateDisplayListIfDirty(View.java:15341)
    at android.view.View.draw(View.java:16143)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3622)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3409)
    at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:663)

可能原因:
Image组件中属性resizeMode设置为了stretch,stretch只支持iOS,所以在Android系统上可能会造成崩溃。可以考虑用contain或cover来代替。

// 这样写,在Android系统上可能会崩溃
<Image ... resizeMode={'stretch'} />

5、React Native 0.55.4(其他版本可能也有类似问题),Text中包含中英文时,如果设置了lineHeight,在iOS上中英文是底部对齐,而不是垂直对齐。

这个版本的Text绘制时是使用的NSMutableAttributedString,居然是按字符来设置baseline,这样中英文这种高度不一样的字符就不会垂直对齐了。

解决办法一:更新到最新版本
解决办法二:直接改源码
将RCTTextShadowView.m文件中postprocessAttributedText方法替换为如下代码:

- (void)postprocessAttributedText:(NSMutableAttributedString *)attributedText
  __block CGFloat maximumLineHeight = 0;
  [attributedText enumerateAttribute:NSParagraphStyleAttributeName
                             inRange:NSMakeRange(0, attributedText.length)
                             options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
                          usingBlock:
    ^(NSParagraphStyle *paragraphStyle, __unused NSRange range, __unused BOOL *stop) {
      if (!paragraphStyle) {
        return;
      maximumLineHeight = MAX(paragraphStyle.maximumLineHeight, maximumLineHeight);
  if (maximumLineHeight == 0) {
    // `lineHeight` was not specified, nothing to do.
    return;
  __block CGFloat maximumFontLineHeight = 0;
  [attributedText enumerateAttribute:NSFontAttributeName
                             inRange:NSMakeRange(0, attributedText.length)
                             options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
                          usingBlock:
    ^(UIFont *font, NSRange range, __unused BOOL *stop) {
      if (!font) {
        return;
      if (maximumFontLineHeight <= font.lineHeight) {
        maximumFontLineHeight = font.lineHeight;
  if (maximumLineHeight < maximumFontLineHeight) {
    return;
  CGFloat baseLineOffset = maximumLineHeight / 2.0 - maximumFontLineHeight / 2.0;
  [attributedText addAttribute:NSBaselineOffsetAttributeName
                         value:@(baseLineOffset)
                         range:NSMakeRange(0, attributedText.length)];

解决办法三:使用runtime方式替换postprocessAttributedText为解决办法二的实现

6、iOS的TextInput组件如果设置的value值字符串长度大于设置maxLength,则maxLength长度控制无效,可以无限输入

除了设置value字符串长度大于maxLength这种情况外,多个手指同时按键盘快速输入,也可能出现这种无限输入的情况。

// RCTBaseTextInputView.m
if (_maxLength) {
    NSUInteger allowedLength = _maxLength.integerValue - backedTextInputView.attributedText.string.length + range.length;
    if (text.length > allowedLength) {

这里的allowedLength可能是一个负数,但定义的类型却是NSUInteger,这时allowedLength就会被转化成一个很大的数字,导致text.length > allowedLength一直是NO
解决办法一:更新到最新版本,我已经提交了PR
解决办法二:直接改源码

// RCTBaseTextInputView.m
if (_maxLength) {
    NSInteger allowedLength = _maxLength.integerValue - backedTextInputView.attributedText.string.length + range.length;
    if (allowedLength < 0 || text.length > allowedLength) {

7、React Native开发的App中的字体会随着系统字体的设置而放大缩小,有时会引起界面显示混乱

解决办法:禁止字体缩放
RN中用于显示的控件就是TextInput和Text,所以只要全局设置它们不可缩放字体就可以了,代码如下:

TextInput.defaultProps = Object.assign({}, TextInput.defaultProps, {
  allowFontScaling: false
Text.defaultProps = Object.assign({}, Text.defaultProps, {