React-Native采坑日记
RN踩坑
环境错误
第一次接触
RN
,肯定是从配置环境入手,完成了双端的编译运行,这仅仅是个开始 关于RN的各种报错原因及解决方案,可以参考这位大神的总结
React Native开发错误警告处理总结(已解决 !持续更新补充:
如果偶尔遇到了一些网上搜不到的报错信息,或者尝试了网上的方法无效,不妨关掉Debug模式,关闭调试浏览器页面,关闭模拟器,关闭js服务,重新run一次,偶尔的情况下,不做任何调整就能恢复正常,还有调试模式下无法断点拦截,或者断点错位,都可以试试
我在配置RN环境中遇到的错误及解决方案总结flex
布局第一次使用
flex
布局,上手写了个非常非常简单的界面(修改密码功能),写完后跑在Android
机上,键盘弹起后,发现控件的高度被挤压了.....- 解决方案:
- 设定高度
display
: 布局中使用了绝对布局,那么display
将在Android下失效解决方案:
设定控件的宽高,来达到控件显隐的控制效果
TextInput
: iOS下TextInput
中文BUG
解决方案:
RN版本还处于不断更新完善中,项目中一旦决定采用了某个指定版本,一般不会轻易升级RN版本,例如我们项目使用的是
v55.4
,iOS
下TextInput
输入中文的BUG
相信不少人应该遇到过了,网上也有很多临时解决方法,但我感觉都不太完善,按照网上的方法可以解决原生输入法的问题,但是在搜狗输入法下还是会有点问题,在后续的RN版本中已经修复了这个BUG,由于项目不打算升级RN版本,采取了修改源码的方式来修复这个BUG,麻烦的就是,要修改开发环境的源码,同时还要修改构建机源码,避免今后构建机npm install
后问题复现,还要在脚本中特殊处理,避免今后出现问题TextInput Fix controlled TextInput for Chinese (and other languages) #18456
stickyHeaderIndices
会导致后一个控件二次调用componentDidMount
方法用过RN的人不一定熟悉这个属性,它是ScrollView用于控制内部某个子控件是否悬挂的,如果你的页面没有什么特殊场景,可能不会造成什么影响,然后我们需要悬挂的是个
WebView
,内嵌了一个H5的MapView
,别问我为啥这样,因为这样就不需要客户端挂VPN了,同时这个控件下面的界面稍微复杂一点,是单独封装了一个用于展示路线的控件,包括途径地点,两点之间的出行方式,详细步骤等介绍解决方案:
调整控件顺序,尽量找一个即便是
componentDidMount
被多次调用了,也不会产生什么影响的控件在悬挂控件下面,如Modal
的控件FlatList
的ListFooterComponent
列表中常见的场景,当列表数据全部加载完毕,会提示“全部加载完毕”, 先描述下我的实现方式 界面顶部一个导航栏,下面一个列表触底,界面布局没有使用
Flex
, 而是通过屏幕的高度直接限定 当显示"全部加载完毕"时,iOS
下正常,而Android
下没有显示,正当我一脸懵逼的时候,给ListFooterComponent
加了个背景色,给FlatList
加了个marginbottom
,发现Android
的ListFooterComponent
这货超出屏幕了解决方案:
起初的解决方案是,在Android下加了一个间距,最后是设置了
render
中最外层View
的flex
react-native-view-shot截图,
Android
下报错:Trying to resolve view with tag XXXX which doesn't exist
on Android, getting "Trying to resolve view with tag '{tagID}' which doesn't exist"
- you need to make sure collapsable is set to false if you want to snapshot a View. Some content might even need to be wrapped into such to actually make them snapshotable! Otherwise that view won't reflect any UI View. (found by @gaguirre)
Alternatively, you can use the ViewShot component that will have collapsable={false} set to solve this problem.
先来说下界面结构:
-ScrollView
----WebView 需要截取的控件
----View 绝对布局的一个遮罩层
-ScrollView业务需求,整个页面都是H5写的,当点击截屏的时候,
H5
会将WebView
中的H5
页面完全展开,返回一个高度,然后RN这边根据高度截取整个H5页面,本身我是一个iOS Developer
,按理讲WebView里面也是有个ScrollView
的,但是截屏后死活不对,只有一屏大小;于是将外层View
节点改成了ScrollView
,当截屏的时候,重新设置WebView
的高度,将ScrollView
撑起来,iOS
可以了,但是Android
上一跑,就红屏了,报这个错误,按照方法试过无效,也有说设置背景色的,仍然不行,最后调整了下布局,直接截ScrollView
;这还没完,iOS
模拟器上截图模糊,而Android
一直是真机运行没有此问题,后来改用iPhone
真机调试,没有了模糊的问题,但当H5
页面展开过长,截取的图片为纯白色空白页面,起初怀疑和ScrollView
嵌套Webview
有关,但通过demo
排除,暂时留存,打算后面再通过分段截图的方式处理
ReacNative
:iOS
正常,Android
报错Cannot add a child that doesn't have a YogaNode to a parent without a measure function!
写好一个界面,iOS跑完全没问题,Android直接Crash,提示
ReacNative:报错Cannot add a child that doesn't have a YogaNode to a parent without a measure ...
这类信息,一脸懵逼,网上搜到了这篇文章:传送门,因为界面内的所有模块都是抽出去写的,然后开始定位排查,最终定位到一个页面,在View
标签中间多了空格,我使用的环境是VS Code
,虽然VS Code
有自动保存的功能,但我使用任何工具都习惯默认状态,每次写完代码Alt + Shift + F
,然后CMD + S
, 但是对于View标签间没有子控件的情况,并不会帮我去空格,因此发生了这个BUG建议:这类没有内部子控件的标签,尽量使用自闭和标签, 如
<View/>
用户授权
当App中需要用到相机,访问一些传感器就会需要获取用户授权,在最初接到这个需求的时候,翻了翻RN的资料,然后发现了一个别人封装好的组件
react-native-permissions
,以前对Android
适配稍微有点了解,刚好手上就有一台华为测试机,经测试效果还可以,正当我美滋滋的完成任务构建送测,测试那边反馈,两台小米都没有任何反应,开始排查问题...发现在小米手机上直接失败,考虑到国内手机厂商对Android
的各种所谓‘定制’,RN
默认提供的方式可能有些‘不接地气’,另外遇到的一个恶心的地方是react-native-permissions
导致上TestFlight
处理完一闪消失解决方案
Android
稳妥起见,我先检查授权情况,如果授权失败了,自己再加个Alert
,提示跳到系统设置页手动开启权限iOS
也是授权问题,当时没看这个库的源码,里面使用了很多我们未曾用到的权限代码,,在plist
中全部加上即可缺点是
个别机型通过获取授权能够弹出提供授权选项,会遇到多次弹框,而之前发现有问题的小米机型上指挥收到一次自定义弹框。
为啥没有跳到对应App的权限设置页,因为我对Android
不熟,搜出来了适配所有国内手机厂商的代码,看的我难受2020-07-20
好久没写过RN
了, 换了设备随着上次升级TypeScript
这次重新回到RN
又一次升级了, 重新搭建React-Native
环境, 因为0.62
更换了CocoaPods
管理iOS
依赖库, 准备先把Android
环境跑通, 首次执行react-native run-android
遭遇滑铁卢, 情理之中, 意料之内.在运行
react-native run-android
后报错如图:
进入路径下对比发现:
分别去了上层目录下对比发现, 很有可能是文件没有下载完整导致, 反复执行react-native run-android
都是没有意义的, 于是删除文件后, 重新执行react-native run-android
等待下载安装依赖包
从终端的输出信息来看, 我的猜想是正确的, 最后对比了下文件正确的样子2020-07-20
安装CocoaPods
依赖库失败, 因为项目使用到了react-native-fast-image
, 这个库是基于SD
的封装,SD
又使用到了libwebp, 在CDN
加持下, 经过一系列依赖库的安装等待后, 迎来了iOS
环境的首个报错:Cloning into '/var/folders/6s/5hf9z6_138v68pqd7v891pd80000gn/T/d20200720-84015-8v2sj1'... fatal: unable to access 'https://chromium.googlesource.com/webm/libwebp/': Failed to connect to chromium.googlesource.com port 443: Operation timed out
通过域名和报错信息也能猜出来啥原因了, 暂时想到两个方案:
- 终端fq
- 修改源 这里采取
方式2
, 修改源的方案
1. 先确认下项目`react-native-fast-image`版本 ~> `8.1.5` 2. `react-native-fast-image`版本依赖的`SDWebImageWebPCoder `版本 ~> '~> 0.6.1' 3. 在本地`pod`源仓库中找到`libwebp`并修改源 默认源: `https://chromium.googlesource.com/webm/libwebp` 替换成: `https://github.com/webmproject/libwebp.git`
换源保存后重新执行
pod install --verbose --no-repo-update
结果失败, 一看错误, 源地址没变, 如果你仔细看过, 在描述文件路径及默认源
这张图中可以发现疑点, 我使用了Trunk
源, 但是改的是Master
中的源地址, 而我podspec
也优先指定了Trunk
源, 所以上一步换源无效, 重新修改对应的源地址后, 执行中验证确认修改成功 到此完成CocoaPods
依赖库安装补充:
关于libwebp
路径我已经在截图中展示了, 没有详细介绍, 可以根据我截图中的路径直接查找, 为了解决复杂的环境及场景, 可以通过find path -iname libwebp
来查找路径:e.g.
shenyj@ShenYj-MBP Desktop % find >/Users/shenyj/.cocoapods/repos/trunk -iname libwebp /Users/shenyj/.cocoapods/repos/trunk/Specs/1/9/2/libwebp