react-native-navigation的迁移库

advanced-navigation.mdx 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. ---
  2. id: advanced-navigation
  3. title: Advanced navigation
  4. sidebar_label: Advanced navigation
  5. ---
  6. import useBaseUrl from '@docusaurus/useBaseUrl';
  7. ## Tab navigation
  8. As mobile applications become bigger and more complex, they usually end up containing multiple primary high-level destinations, which are logically independent from one another. The `BottomTabs` layout is often used when an app contains three to five top-level destinations which should be accessible from anywhere in the app.
  9. Lets return to the example code from the previous section ([Basic navigation](basic-navigation.mdx)) and see how we can convert it to a tab-based application. We'll use the BottomTabs layout to display tabs at the bottom of the screen. Similarly to `Stack` layout, The BottomTabs layout also contains a `children` property where each child will be displayed in a tab.
  10. Lets change our code to the following and reload the app.
  11. ```jsx
  12. const Navigation = require('./services/Navigation');
  13. const React = require('react');
  14. const { View, Text, Button, StyleSheet } = require('react-native');
  15. const HomeScreen = (props) => {
  16. return (
  17. <View style={styles.root}>
  18. <Text>Hello React Native Navigation 👋</Text>
  19. <Button
  20. title='Push Settings Screen'
  21. color='#710ce3'
  22. onPress={() => Navigation.push(props.componentId, {
  23. component: {
  24. name: 'Settings'
  25. }
  26. })} />
  27. </View>
  28. );
  29. };
  30. HomeScreen.options = {
  31. topBar: {
  32. title: {
  33. text: 'Home'
  34. }
  35. },
  36. bottomTab: {
  37. text: 'Home'
  38. }
  39. };
  40. const SettingsScreen = () => {
  41. return (
  42. <View style={styles.root}>
  43. <Text>Settings Screen</Text>
  44. </View>
  45. );
  46. }
  47. SettingsScreen.options = {
  48. topBar: {
  49. title: {
  50. text: 'Settings'
  51. }
  52. },
  53. bottomTab: {
  54. text: 'Settings'
  55. }
  56. }
  57. Navigation.registerComponent('Home', () => HomeScreen);
  58. Navigation.registerComponent('Settings', () => SettingsScreen);
  59. Navigation.setDefaultOptions({
  60. statusBar: {
  61. backgroundColor: '#4d089a'
  62. },
  63. topBar: {
  64. title: {
  65. color: 'white'
  66. },
  67. backButton: {
  68. color: 'white'
  69. },
  70. background: {
  71. color: '#4d089a'
  72. }
  73. },
  74. bottomTab: {
  75. fontSize: 14,
  76. selectedFontSize: 14
  77. }
  78. });
  79. Navigation.events().registerAppLaunchedListener(async () => {
  80. Navigation.setRoot({
  81. root: {
  82. bottomTabs: {
  83. children: [
  84. {
  85. stack: {
  86. children: [
  87. {
  88. component: {
  89. name: 'Home'
  90. }
  91. },
  92. ]
  93. }
  94. },
  95. {
  96. stack: {
  97. children: [
  98. {
  99. component: {
  100. name: 'Settings'
  101. }
  102. }
  103. ]
  104. }
  105. }
  106. ]
  107. }
  108. }
  109. });
  110. });
  111. const styles = StyleSheet.create({
  112. root: {
  113. flex: 1,
  114. alignItems: 'center',
  115. justifyContent: 'center',
  116. backgroundColor: 'whitesmoke'
  117. }
  118. });
  119. ```
  120. Now our app has two tabs at the bottom of the screen and our users can easily navigate between them.
  121. <img width="40%" src={useBaseUrl('img/stack4.png')} />
  122. ## Replacing the root
  123. Up until now, we've discussed how to navigate within the same layout structure. We'll now learn how to replace the entire layout structure to display a new Root. A real life example for this use case would be, for instance, if you need to switch from a login screen to the app's main root. Replacing the root fits this use case since we'd like to discard the previous root (login root) entirely when switching to the main root.
  124. To demonstrate this, we'll make the following changes to our code:
  125. 1. Add a login screen with a login button.
  126. 2. When the button is clicked, we will switch to the main root.
  127. 3. Replace our current root with the login screen. We'll also extract both roots to variables to improve code readability.
  128. ```jsx
  129. const LoginScreen = () => {
  130. return (
  131. <View style={styles.root}>
  132. <Button
  133. title='Login'
  134. color='#710ce3'
  135. onPress={() => Navigation.setRoot(mainRoot)}
  136. />
  137. </View>
  138. );
  139. };
  140. const HomeScreen = (props) => {
  141. return (
  142. <View style={styles.root}>
  143. <Text>Hello React Native Navigation 👋</Text>
  144. <Button
  145. title='Push Settings Screen'
  146. color='#710ce3'
  147. onPress={() => Navigation.push(props.componentId, {
  148. component: {
  149. name: 'Settings'
  150. }
  151. })} />
  152. </View>
  153. );
  154. };
  155. HomeScreen.options = {
  156. topBar: {
  157. title: {
  158. text: 'Home'
  159. }
  160. },
  161. bottomTab: {
  162. text: 'Home'
  163. }
  164. };
  165. const SettingsScreen = () => {
  166. return (
  167. <View style={styles.root}>
  168. <Text>Settings Screen</Text>
  169. </View>
  170. );
  171. }
  172. SettingsScreen.options = {
  173. topBar: {
  174. title: {
  175. text: 'Settings'
  176. }
  177. },
  178. bottomTab: {
  179. text: 'Settings'
  180. }
  181. }
  182. Navigation.registerComponent('Login', () => LoginScreen);
  183. Navigation.registerComponent('Home', () => HomeScreen);
  184. Navigation.registerComponent('Settings', () => SettingsScreen);
  185. const mainRoot = {
  186. root: {
  187. bottomTabs: {
  188. children: [
  189. {
  190. stack: {
  191. children: [
  192. {
  193. component: {
  194. name: 'Home'
  195. }
  196. },
  197. ]
  198. }
  199. },
  200. {
  201. stack: {
  202. children: [
  203. {
  204. component: {
  205. name: 'Settings'
  206. }
  207. }
  208. ]
  209. }
  210. }
  211. ]
  212. }
  213. }
  214. };
  215. const loginRoot = {
  216. root: {
  217. component: {
  218. name: 'Login'
  219. }
  220. }
  221. };
  222. Navigation.setDefaultOptions({
  223. statusBar: {
  224. backgroundColor: '#4d089a'
  225. },
  226. topBar: {
  227. title: {
  228. color: 'white'
  229. },
  230. backButton: {
  231. color: 'white'
  232. },
  233. background: {
  234. color: '#4d089a'
  235. }
  236. },
  237. bottomTab: {
  238. fontSize: 14,
  239. selectedFontSize: 14
  240. }
  241. });
  242. Navigation.events().registerAppLaunchedListener(async () => {
  243. Navigation.setRoot(loginRoot);
  244. });
  245. const styles = StyleSheet.create({
  246. root: {
  247. flex: 1,
  248. alignItems: 'center',
  249. justifyContent: 'center',
  250. backgroundColor: 'whitesmoke'
  251. }
  252. });
  253. ```
  254. ## Conditional roots
  255. Now that our initial root is the Login root, we're facing a new problem - how do we show the Login root only to users that are not logged in? Since our initial root is determined in the `registerAppLaunchedListener` callback, we'll check if a user is logged in there and set the appropriate root accordingly.
  256. ```jsx
  257. Navigation.events().registerAppLaunchedListener(async () => {
  258. Navigation.setRoot(isLoggedIn() ? mainRoot : loginRoot);
  259. });
  260. function isLoggedIn() {
  261. // TODO: your business logic goes here
  262. }
  263. ```