Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React+RN开发过程中的一些问题总结(持续更新。。。) #52

Open
amandakelake opened this issue Jun 11, 2018 · 15 comments

Comments

@amandakelake
Copy link
Owner

amandakelake commented Jun 11, 2018

写RN的过程中踩过大大小小的坑,有些解决了,有些还等挖掘更好的方案,甚至有些解决不了的就直接绕道了(希望有大神指导一下),也一并记录下来好了,这部分也会持续更新。。。
可惜有些问题解决完就忘了,没记录下来,特别是调试、真机、平台方面的

题外话:有些当初苦苦想破脑袋的坑,踩过后才发现是如此的弱🐔,本来是不应该show出来贻笑大方的,但万一就是有小白也刚好陷入跟我当初一样的思维怪圈呢?所以不怕大家笑话,就一股脑都写下来吧,若干年后回头一看:原来当年我傻的如此可爱,能博得自己一笑,不也挺有意思的么

一、如何解决问题

这里科普一下自己遇到问题的通用解决办法

1、看官方文档,很多问题官方都已经考虑到了,对着关键词搜
这里要吐槽一句,RN的中文文档是真滴烂,推荐看英文文档(看不懂就好好学英语)
2、google (不要百度)
google出来的列表里面,优先看github的issue,其次看stackoverflow,然后才是其他的选项
e3d09196-d76a-469f-9653-953dc2eb5194

3、问同事(一定要再自己google后),问你认识的大神好友
带着清晰的问题,傻逼问题就别问了

4、以上三板斧都解决不了的话,信佛的阿弥陀佛,信基督的阿门吧

二、问题记录

PS:下面的问题全都没有按照顺序或者时间分类,大部分是以前自己随手记录的笔记,就是辛苦一些看文章的小伙伴了,或者可以cmd+F或者ctrl+F直接搜索自己需要的内容

1、RN:子元素宽度问题、位置居中

RN默认使用flex布局,子元素不用设置宽度,会自动拉伸满容器
45667b71-3ed7-46db-90d1-e012388c947a

如果子元素想居中
除了使用父元素的alignItems: 'center'
还是可以使用子元素的alignSelf: 'center'
这样子的话子元素的宽度不再拉伸,会按照实际内容宽度,如下

export default class PopularizeHome extends Component<Props> {
  render() {
    return (
      <View>
        <View style={styles.childContainer}>
          <Text>PopularizeHome</Text>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  childContainer: {
    // alignSelf: 'center',
    backgroundColor: 'red'
  },
});

29240659-9956-4da3-b58f-047da63750ab

2、RN:使用原生的Navigator时隐藏TarBar底部导航栏

会有小bug,最好是用react-navigation或者react-native-navigation
f6e90656-f5b8-4372-a5b9-324e53413ecc

3、RN:HTTP安全限制

iOS9 & iOS10 HTTP 不能正常使用的解决办法 - iOS前沿 - SegmentFault
46b2ab74-1601-4e9a-9446-937336ae079f
50754b81-27fd-4f0f-b2f6-6f57848886dc

4、React:swiper高度限制

swiper自带的的高度是属性控制,不是样式控制
可以在swiper外面套一层来控制高度

5、React:循环渲染时,onPress事件不需要再把item当做参数

否则会拿不到正确的item值
886e1618-d743-415a-a5ee-7d52e5b2fdc6
bd9af936-ae2a-40e6-90d5-7e7fc20a6163

6、fecth使用formData上传数据

11f82003-de60-4be3-a914-aa9de3735073

7、TextInput右边的padding会超出屏幕

flex:1无法读取宽度,需要计算屏幕宽度
6085bd15-316d-40a9-9bb0-e07c0e3f54c6
e9508e7c-6a15-4206-874c-726f3bc83ff9

8、react-navigation的设置navigationOptions里面读取state的数据和绑定方法

需要记得bind(this)
fa70e3e0-78a6-43b3-995e-7ea56742114c

9、复用input[radio]组件时,ID必须唯一,否则会两个input[radio]之间造成串联,互相影响

1b6ac217-52ea-4750-9f2a-13fdd1cdba4e

10、RN:AsyncStorage本地存储,setItems时要用string,不能用到其他类型

setAsyncStorageIsLaunched() {
    AsyncStorage.setItem('HAS_LAUNCHED',true).then(() => {
      console.log('第一次登录成功',this.getAsyncStorageIsLaunched());
    });
  }

d690b9bd-beb5-41e5-a68a-26ce25e6a563

11、RN: source.uri should not be an empty string

有可能后台真的没有返回图片链接,虽然不是红色错误,黄色warning也很烦,做好三元判断就好了

{card.bank_background ? <Image
  style={styles.itemBgIcon}
  resizeMode="contain"
  source={{ uri: card.bank_background }}
/> : null}

12、对于一些依靠后台数据的地方,做好拿不到数据或者错误数据的准备,给一个默认值,防止报错

比如这里,一个渐变模块,后台如果不给颜色,那就会直接报错
b8009866-a6db-43a4-8416-2faef8233be4

还有一个最常见的情况,数组的渲染,做好多重保险
b11f74a8-9650-4144-82c5-c4c8c29868c8

13、Raw text cannot be used outside of a tag. Not rendering string: ''

{card.status_name && (
  <View style={styles.itemTopRight}>
    <Text style={styles.itemTopRightText}>{card.status_name}</Text>
  </View>
)}

try the !! trick to make sure you only use booleans

{!!card.status_name && (
  <View style={styles.itemTopRight}>
    <Text style={styles.itemTopRightText}>{card.status_name}</Text>
  </View>
)}

Or use the ? : 三元运算符

{card.status_name ? (
  <View style={styles.itemTopRight}>
    <Text style={styles.itemTopRightText}>{card.status_name}</Text>
  </View>
) : null}

14、React Native ListView 需触摸/滑动后才显示的问题,官方Issues:

点这里

// 需要在初始化 ListView 时添加以下参数配置
removeClippedSubviews={false}

15、ListView的问题

4884a83d-91b2-41b9-9b0b-ddae3f8f9806

16、使用FlatList的注意事项

1a27cad1-e885-4dc3-a93e-230ca8ca0d20

17、安卓的物理返回键盘(防止直接退出应用)

监听返回事件,改写
移除组件的时候,移除监听
35667ac4-91fb-4fd9-98c8-a1416cae5b28

18、RN:0.44版本后,Navigator和BackAndroid组件都不存在了

从0.44版本开始,Navigator不再从‘react-native’中引入,而是需要

npm install react-native-deprecated-custom-components –save

并在代码中引入

import { Navigator } from 'react-native-deprecated-custom-components'

同样从0.44版本开始,BackAndroid组件不在出现,而是用BackHandler代替

19、在render函数中中循环修改state,导致最后栈溢出

f0902ea9-4a98-4131-8590-1efead864162
0b69c191-a047-4872-aa66-61f4b06b3976

看下面,是罪魁祸首
应该是定义函数,而不是直接执行
7cb4030a-9f12-4878-9a25-ebd7d1732719

20、开debug模式时load bundle 100% 卡住(未解决),关掉远程debugger就就OK,需要重启电脑解决

WebSocket connection to ‘ws://localhost:8081/debugger-proxy?role=debugger&name=Chrome’ failed: Invalid frame header · Issue #6627 · facebook/react-native · GitHub
React-Native Error: Connection to http://localhost:8081/debugger-proxy?role=client timed out - Stack Overflow

还没解决
RCTModuleData deadlock when running with debugger · Issue #11196 · facebook/react-native · GitHub
RCTBridge required dispatch_sync to load RCTDevLoadingView. This may lead to deadlocks · Issue #16376 · facebook/react-native · GitHub

具体什么情况我也不是很清楚,mac的话,重启电脑就好了(我试验了很多次)

  • 首先需要设置IP和端口,默认端口是8081,手机(模拟器)和电脑在同一个网络中,查询电脑的IP地址。
  • 手动去删除.babelrc隐藏文件,具体文件目录为node_modules/react-deep-force-update/.babelrc
  • 如果是其他版本,那也是需要删除的不过路径已经发生变化了。具体路径:/node_modules/react-native/node_modules/react-transform-hmr/node_modules/react-proxy/node_modules/react-deep-force-update
  • 最后重点 Android项目关闭终端重新执行运行命令,iOS项目也需要关闭服务终端,重新启动packager

21、子组件有复杂的数据和操作,需要父组件触发更新,但不想提升到父组件

使用componentWillReceiveProps增加父组件的标志位,子组件检测到父组件传下来的该标志位的变化时,即可触发更新

componentWillReceiveProps(nextProps) {
    if (nextProps.needUpdatePopularize !== this.props.needUpdatePopularize) {
      this.onRequestData();
      this.requestRank();
    }
  }

22、Task orphaned for request <NSMutableURLRequest: 0x1c4202170>

Unmount images while loading · Issue #12152 · facebook/react-native · GitHub
图片还没完全加载完成的过程中,就触发其他操作,比如页面跳转,这时候又需要unmount 图片,就会出现这些黄色warning
同理,FlatList如果有很多图片要渲染,上下拉刷新时也会出现这些情况

23、安卓打包错误

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:validateSigningRelease'.
> Keystore file /Users/macbookpro-luoguangcong/projects/newapp/android/app/my-release-key.keystore not found for signing config 'release'.

android/app文件夹下面缺一个my-release-key.keystore文件,去旧项目复制过来即可

24、打包realease包的时候报错 main.jsbundle does not exist. This must be a bug with + echo 'React Native

先打包debug版本 看看有没有JS代码错误
如果确认OK,再重新yarn一次

25、webview 监听页面变化(不是自己写的H5,没办法使用postMessage)

96fe8710-9d55-42d2-b8e5-d4b8306e4fcb

_onNavigationStateChange(webViewState) {
    // console.log('webview ???', webViewState);
    if (webViewState.url.indexOf('*****') >= 0) {
      this.props.repaymentActions.repaymentSetCreditCardListNew();
      this.props.navigator.pop();
    }
  }

26、传参问题 企图修改原型属性

One of the sources for assign has an enumerable key on the prototype chain. Are you trying to assign a prototype property? We don't allow it, as this is an edge case that we do not support. This error is a performance optimization and not spec compliant.

451d9db7-847d-414f-9242-bb21cf12fab3

该传的参数还是得传
bc76b168-f431-435e-bb51-9e589072df17

27、关闭弹窗后自动执行两次路由操作

点击弹出框Btn => 收起弹框 => 切换tab => push进其他页面
1、收起弹框、切换tab,easy
2、当前处于什么scene就切换什么scene
3、在切换后的“我的“页面通过componentWillReceiveProps监听scene的变化,然后push到对应的组件去

d1e051b0-3de0-485e-b10c-a112b8874f69

28、App与webview(H5)通信

postMessage发送消息

sendMessage(data) {
    this.webview.postMessage(data);
  }

onMessage监听

<WebView
  injectedJavaScript={ debug}
  style={}
  source={{ uri: *** }}
  userAgent={'GuardianAppIOS/1.0.0 Webview'}
  onMessage={this.handleMessage}
/>

但这里有个bug
react native html postMessage can not reach to WebView · Issue #11594 · facebook/react-native · GitHub

// the react native postMessage has only 1 parameter while the default one has 2, so check the signature of the function
  waitForBridge(option) {
    if (window.postMessage.length !== 1) {
      setTimeout(() => {
        this.waitForBridge();
      }, 200);
    } else {
      window.postMessage(
        JSON.stringify(option)
      );
    }
  }

通过观察者(发布-订阅)模式进行页面的跳转
先实例化一个事件发布器

import EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter'

let emitter = new EventEmitter()

export default emitter
if (url.startsWith('http://') || url.startsWith('https://')) {
    return emitter.emit('NAVIGATION_NAVIGATE_TO', 'WebView', url, extraData)
  }

在navigator进行监听,以及销毁时的移除

// add eventlistener: navigate to
    emitter.addListener('NAVIGATION_NAVIGATE_TO', (routeName, url, extraData) => {
      this.props.dispatch(
        NavigationActions.navigate({
          routeName,
          params: routeName === 'WebView' ? { url, ...extraData } : {},
        })
      )
    })
componentWillUnmount() {
    emitter.removeAllListeners()
  }

29、配置schemes URL

React Native URL Scheme and Linking API - Johnson Su
非常棒的指引

30、切换App主题

1、替换整个app(理解为品牌)
将所有color、size、position相关属性抽离出来,放到一个公共文件commonStyles.js,导出常量使用
该文件根据config.js中的THEME进行判断采用哪一套主题
如此,只需要修改THEME即可,达到一键替换的作用

2、app换皮肤
新建一个BaseCommon.js页面,作为这四个页面的父类。在这个父类里面接收主题更改的通知,并更新自己的主题。这样一来,继承它的这四个页面就都会刷新自己

31、中间模态窗

大概思路:
1、第三个导航样式上采用区别对待,该tab本来在路由系统中对应了一个页面组件,现在设置为null,改写它的点击事件(其他四个按钮则是正常的切换tab事件),点击则出现全屏弹层
f93afb37-0fba-48fe-ad99-4e7e5ed5aa6a

2、为实现弹层效果,给一个动画效果,并占满全屏
02145d25-a1e6-4e70-b22b-07c65acaa263

wrapper: {
    position: 'absolute',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
    backgroundColor: templateUsage.shouldUseTemplateDaily()
      ? '#191A22'
      : 'rgba(40, 47, 51, 0.8)',
  },

3、弹层上的路由设置
直接抛弃掉真正的路由系统,用状态来控制页面的隐藏和显示,假装是push进一个页面,其实只是由一个state状态来控制一个页面显示,一个页面隐藏而已

消失或者隐藏,也就是加个动画,然页面更自然

closePopularize() {
    this.state.y.setValue(0);
    Animated.timing(this.state.y, {
      toValue: Dimensions.get('window').height,
      duration: 200
    }).start(this.props.popPopularize);
  }

  clearPopularize() {
    this.state.y.setValue(0);
    Animated.timing(this.state.y, {
      toValue: Dimensions.get('window').height,
      duration: 200
    }).start(this.props.clearPopularize);
  }
@amandakelake amandakelake changed the title RN踩坑记录总结(持续更新。。。) React+RN开发过程中的一些问题总结(持续更新。。。) Jul 15, 2018
@ghost
Copy link

ghost commented Jul 19, 2018

总结的很好,另外还有个坑,ios9.0和10版本SafeAreaView组件不支持,需要手动判断

@amandakelake
Copy link
Owner Author

@shx1545 噢 对,这个忘了写了 感谢大佬

@ghost
Copy link

ghost commented Aug 10, 2018

@amandakelake react-native自带的SafeAreaView组件是不支持ios10及以下,如果要用了react-navigation,可以引入它里面的。
import {SafeAreaView} from 'react-navigation'

@amandakelake
Copy link
Owner Author

@shx1545 嗯嗯 对的

@yezidd
Copy link

yezidd commented Sep 26, 2018

请问一下25有没有什么好的方案可以解决

@amandakelake
Copy link
Owner Author

@yezidd 不是已经写出来了么 监听页面url的变化

@Circleee
Copy link

webview 里面 alert 没有反应 , 这个可以解决吗?

@weifengzz
Copy link

第21,生命周期中的componentWillReceiveProps 将要弃用了,使用�新的 getDerivedStateFromProps

@jim888666
Copy link

您好,请问下,一个App唤醒另一个App并且传参 ,react-native 能做到吗??

@amandakelake
Copy link
Owner Author

@jim888666 你搜索一下Linking看看

@mrzxc
Copy link

mrzxc commented Jun 19, 2019

22条在FlatList中的image未卸载bug 应该是已经修复了

@Liu-10004
Copy link

安卓的字体偏大,在屏幕上总是会出现文字被挡住一点,这个该怎么搞

@ZosenZhao
Copy link

com.facebook.jni.CppException: Could not get BatchedBridge, make sure your bundle is packaged correctly

这个是什么原因?大佬

@ciloi
Copy link

ciloi commented Apr 17, 2024 via email

@ZosenZhao
Copy link

com.facebook.jni.CppException: Could not get BatchedBridge, make sure your bundle is packaged correctly

这个是什么原因?大佬

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants