记录一些自己入门遇到的问题与解决方法
怎么将navigation传递到子级组件?
当需要在子组件中使用navigation
导航时,一种方法是直接在引入组件时将 navigation 作为props传递,另一种是使用 withNavigation
,后者更优雅。
方法一:引用时传递
1 | <Component navigation={this.props.navigation} ...otherProps /> |
方法二:使用 withNavigation
, 参见官方文档
1 | import React from 'react'; |
然后在引入时更直接:1
<Component ...otherProps />
RN在iOS真机、模拟器调试时网络兼容问题
在RN生成的XCode项目里,默认是通过远程方式调试,只要手机、模拟器处于同一网络即可,但我们的手机极有可能会切换网络(譬如上下班、吃饭、上厕所…等等),而这会导到远程调试的应用无法打开,可以兼容处理。
打开XCode项目,修改 AppDelegate.m
,将原有的1
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
修改成1
2
3
4
5
6
7#if TARGET_IPHONE_SIMULATOR
// remote debug
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
// release
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
这会将真机像发布时一样把文件打包进APP,不受网络切换影响
获取组件的屏幕位置
当使用react-native-modal-popover
组件时,有一个参数fromRect
用来指明组件的位置,这时候我们取要获取组件的位置,使用NativeModules.UIManager.measure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
findNodeHandle,
NativeModules
} from 'react-native';
import Popover, { PopoverTouchable } from 'react-native-modal-popover';
....
const handle = findNodeHandle(this.refs[ 'popoverAnchor' ]);
if (handle) {
NativeModules.UIManager.measure(handle, (x0, y0, width, height, x, y) => {
this.setState({
popoverAnchor: { x, y, width, height },
});
});
}
....
<SimpleLineIcons
name="options"
ref="popoverAnchor"
...otherProps
/>
<Popover
visible={this.state.showPopover}
fromRect={this.state.popoverAnchor}
...otherProps
>
{children}
</Popover>
基于webview实现简易浏览器
在APP内经常需要打开一些URL链接,如果通过外部浏览器打开、返回体验不好,一般会做一个内部的导航,用RN的WebView组件很容易实现,主要是利用onNavigationStateChange
获得各种状态并处理各导航菜单的表现,同时利用navigation.setParams
动态设置浏览器的标题栏。
1 | ... |
使用react-navigation
的TabNavigator
时Tab之间跳转不能正常返回的情况
如果TabA、TabB同时是StackNavigator
,当从一个TabA跳到另一个TabB里的某个路由时,返回时常常会处于TabB中而无法正常返回到TabA,一种方法是修改顶部左侧菜单自定义实现返回逻辑,但这种情况下右滑返回手势仍然不能正常返回到TabA。
换种思维,直接将TabA要跳转的页面引入到相应的Tab路由中,代码仍然是一套,只是配了两个路由,路由名字略微不同即可:1
2
3
4
5
6
7
8
9
10
11export const RouteHome = StackNavigator({
Home : { screen: Views.Home },
HBrowser: { screen: Views.Browser },
Scanner : { screen: Views.Scanner },
})
export const RouteSetting = StackNavigator({
Setting : { screen: Views.Home },
Browser: { screen: Views.Browser },
ScannerB : { screen: Views.Scanner },
})
上面的 HBrowser
、Browser
用了相同的组件,但路由名不同,在Home
路由中按需跳转HBrowser
,在Setting
中就按需跳转Browser
,这样兼顾了代码复用与交互的问题。
1 | ...... |
UPDATE: 经测试,不同StackNavigator里可以包含同名路由,导航时会优先从该Stack里寻找路由,所以上面的路由在取名时不需要刻意规避,简化如下:
1 | const BaseRoutes = { |
导航时不再区分路由名:1
2
3
4
5
6
7
8
9
10
11
12......
<Hyperlink
onPress={ (url, text) => {
this.props.navigation.navigate('Browser', {url: url, text: text})
}}
linkStyle={styles.url}
>
<Text style={styles.content} selectable={true} selectable={true}>
{item.content}
</Text>
</Hyperlink>
......
StackNavigator里嵌套了TabNavigator
如果TabNavigator里的Views是根据程序动态生成的,那边多半面临导航找不到路由的问题
同时如果组件既在TabNavigator里使用,也有可能直接在StackNavigator里使用,这个时候 navigation
指向不同,需要特殊处理才能兼容
具体方法,参考:https://github.com/react-navigation/react-navigation/issues/335
1 | // Community : CommunityTabs, // 这个方法不能让子级最高层级的 TabBar的情况,譬如按需隐藏 |