tutorial react navigating react-native react-navigation

react-native - navigating - react navigation v2



React-Navigation con pantalla de inicio de sesiĆ³n (11)

Oct 2017 Me pareció ridículamente confuso, así que aquí está mi solución, comenzando de arriba hacia abajo:

Recomiendo comenzar un nuevo proyecto y, literalmente, simplemente pegar todo esto y estudiarlo después. Comenté el código a lo grande, así que si estás atascado en un área específica, tal vez el contexto pueda ayudarte a volver a la normalidad.

Esta publicación muestra cómo:

  1. configura completamente React Native para ejecutar react-navigation
  2. Integrarse adecuadamente con Redux
  3. Manejar el botón Atrás de Android
  4. Navegadores de pila de nidos
  5. Navegar de navegadores de padres a hijos
  6. Restablecer la pila de navegación
  7. Restablezca la pila de navegación mientras navega de secundario a primario (anidado)

index.js

import { AppRegistry } from ''react-native'' import App from ''./src/App'' AppRegistry.registerComponent(''yourappname'', () => App)

src / App.js (este es el archivo más importante porque reúne todos los fragmentos)

import React, { Component } from ''react'' // this will be used to make your Android hardware Back Button work import { Platform, BackHandler } from ''react-native'' import { Provider, connect } from ''react-redux'' import { addNavigationHelpers } from ''react-navigation'' // this is your root-most navigation stack that can nest // as many stacks as you want inside it import { NavigationStack } from ''./navigation/nav_reducer'' // this is a plain ol'' store // same as const store = createStore(combinedReducers) import store from ''./store'' // this creates a component, and uses magic to bring the navigation stack // into all your components, and connects it to Redux // don''t mess with this or you won''t get // this.props.navigation.navigate(''somewhere'') everywhere you want it // pro tip: that''s what addNavigationHelpers() does // the second half of the critical logic is coming up next in the nav_reducers.js file class App extends Component { // when the app is mounted, fire up an event listener for Back Events // if the event listener returns false, Back will not occur (note that) // after some testing, this seems to be the best way to make // back always work and also never close the app componentWillMount() { if (Platform.OS !== ''android'') return BackHandler.addEventListener(''hardwareBackPress'', () => { const { dispatch } = this.props dispatch({ type: ''Navigation/BACK'' }) return true }) } // when the app is closed, remove the event listener componentWillUnmount() { if (Platform.OS === ''android'') BackHandler.removeEventListener(''hardwareBackPress'') } render() { // slap the navigation helpers on (critical step) const { dispatch, nav } = this.props const navigation = addNavigationHelpers({ dispatch, state: nav }) return <NavigationStack navigation={navigation} /> } } // nothing crazy here, just mapping Redux state to props for <App /> // then we create your root-level component ready to get all decorated up const mapStateToProps = ({ nav }) => ({ nav }) const RootNavigationStack = connect(mapStateToProps)(App) const Root = () => ( <Provider store={store}> <RootNavigationStack /> </Provider> ) export default Root

src / navigation / nav_reducer.js

// NavigationActions is super critical import { NavigationActions, StackNavigator } from ''react-navigation'' // these are literally whatever you want, standard components // but, they are sitting in the root of the stack import Splash from ''../components/Auth/Splash'' import SignUp from ''../components/Auth/SignupForm'' import SignIn from ''../components/Auth/LoginForm'' import ForgottenPassword from ''../components/Auth/ForgottenPassword'' // this is an example of a nested view, you might see after logging in import Dashboard from ''../components/Dashboard'' // index.js file const WeLoggedIn = StackNavigator({ LandingPad: { // if you don''t specify an initial route, screen: Dashboard // the first-declared one loads first } }, { headerMode: ''none'' initialRouteName: LandingPad // if you had 5 components in this stack, }) // this one would load when you do // this.props.navigation.navigate(''WeLoggedIn'') // notice we are exporting this one. this turns into <RootNavigationStack /> // in your src/App.js file. export const NavigationStack = StackNavigator({ Splash: { screen: Splash }, Signup: { screen: SignUp }, Login: { screen: SignIn }, ForgottenPassword: { screen: ForgottenPassword }, WeLoggedIn: { screen: WeLoggedIn // Notice how the screen is a StackNavigator } // now you understand how it works! }, { headerMode: ''none'' }) // this is super critical for everything playing nice with Redux // did you read the React-Navigation docs and recall when it said // most people don''t hook it up correctly? well, yours is now correct. // this is translating your state properly into Redux on initialization const INITIAL_STATE = NavigationStack.router.getStateForAction(NavigationActions.init()) // this is pretty much a standard reducer, but it looks fancy // all it cares about is "did the navigation stack change?" // if yes => update the stack // if no => pass current stack through export default (state = INITIAL_STATE, action) => { const nextState = NavigationStack.router.getStateForAction(action, state) return nextState || state }

src / store / index.js

// remember when I said this is just a standard store // this one is a little more advanced to show you import { createStore, compose, applyMiddleware } from ''redux'' import thunk from ''redux-thunk'' import { persistStore, autoRehydrate } from ''redux-persist'' import { AsyncStorage } from ''react-native'' // this pulls in your combinedReducers // nav_reducer is one of them import reducers from ''../reducers'' const store = createStore( reducers, {}, compose( applyMiddleware(thunk), autoRehydrate() ) ) persistStore(store, { storage: AsyncStorage, whitelist: [] }) // this exports it for App.js export default store

src / reducers.js

// here is my reducers file. i don''t want any confusion import { combineReducers } from ''redux'' // this is a standard reducer, same as you''ve been using since kindergarten // with action types like LOGIN_SUCCESS, LOGIN_FAIL import loginReducer from ''./components/Auth/login_reducer'' import navReducer from ''./navigation/nav_reducer'' export default combineReducers({ auth: loginReducer, nav: navReducer })

src / components / Auth / SignUpForm.js

Te mostraré una muestra aquí. Esto no es mío, lo acabo de escribir en este desvencijado editor de StackOverflow. Por favor, denme me gusta si lo aprecian :)

import React, { Component } from ''react'' import { View, Text, TouchableOpacity } from ''react-native // notice how this.props.navigation just works, no mapStateToProps // some wizards made this, not me class SignUp extends Component { render() { return ( <View> <Text>Signup</Text> <TouchableOpacity onPress={() => this.props.navigation.navigate(''Login'')}> <Text>Go to Login View</Text> </TouchableOpacity> </View> ) } } export default SignUp

src / components / Auth / LoginForm.js

También te mostraré uno de estilo tonto, con el botón de retroceso de super droga

import React from ''react'' import { View, Text, TouchableOpacity } from ''react-native // notice how we pass navigation in const SignIn = ({ navigation }) => { return ( <View> <Text>Log in</Text> <TouchableOpacity onPress={() => navigation.goBack(null)}> <Text>Go back to Sign up View</Text> </TouchableOpacity> </View> ) } export default SignIn

src / components / Auth / Splash.js

Aquí hay una pantalla de bienvenida con la que puedes jugar. Lo estoy usando como un componente de orden superior:

import React, { Component } from ''react'' import { StyleSheet, View, Image, Text } from ''react-native'' // https://github.com/oblador/react-native-animatable // this is a library you REALLY should be using import * as Animatable from ''react-native-animatable'' import { connect } from ''react-redux'' import { initializeApp } from ''./login_actions'' class Splash extends Component { constructor(props) { super(props) this.state = {} } componentWillMount() { setTimeout(() => this.props.initializeApp(), 2000) } componentWillReceiveProps(nextProps) { // if (!nextProps.authenticated) this.props.navigation.navigate(''Login'') if (nextProps.authenticated) this.props.navigation.navigate(''WeLoggedIn'') } render() { const { container, image, text } = styles return ( <View style={container}> <Image style={image} source={require(''./logo.png'')} /> <Animatable.Text style={text} duration={1500} animation="rubberBand" easing="linear" iterationCount="infinite" > Loading... </Animatable.Text> <Text>{(this.props.authenticated) ? ''LOGGED IN'' : ''NOT LOGGED IN''}</Text> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: ''center'', alignItems: ''center'', backgroundColor: ''#F0F0F0'' }, image: { height: 110, resizeMode: ''contain'' }, text: { marginTop: 50, fontSize: 15, color: ''#1A1A1A'' } }) // my LOGIN_SUCCESS action creator flips state.auth.isAuthenticated to true // so this splash screen just watches it const mapStateToProps = ({ auth }) => { return { authenticated: auth.isAuthenticated } } export default connect(mapStateToProps, { initializeApp })(Splash)

src / components / Auth / login_actions.js

Solo voy a mostrar initializeApp () para que tengas algunas ideas:

import { INITIALIZE_APP, CHECK_REMEMBER_ME, TOGGLE_REMEMBER_ME, LOGIN_INITIALIZE, LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT } from ''./login_types'' //INITIALIZE APP // this isn''t done, no try/catch and LOGIN_FAIL isn''t hooked up // but you get the idea // if a valid JWT is detected, they will be navigated to WeLoggedIn export const initializeApp = () => { return async (dispatch) => { dispatch({ type: INITIALIZE_APP }) const user = await AsyncStorage.getItem(''token'') .catch((error) => dispatch({ type: LOGIN_FAIL, payload: error })) if (!user) return dispatch({ type: LOGIN_FAIL, payload: ''No Token'' }) return dispatch({ type: LOGIN_SUCCESS, payload: user }) // navigation.navigate(''WeLoggedIn'') // pass navigation into this function if you want } }

En otros casos de uso, puede preferir el componente de orden superior. Funcionan exactamente igual que React para la web. Los tutoriales de Stephen Grider sobre Udemy son los mejores, punto.

src / HOC / require_auth.js

import React, { Component } from ''react'' import { connect } from ''react-redux'' export default function (ComposedComponent) { class Authentication extends Component { componentWillMount() { if (!this.props.authenticated) this.props.navigation.navigate(''Login'') } componentWillUpdate(nextProps) { if (!nextProps.authenticated) this.props.navigation.navigate(''Login'') } render() { return ( <ComposedComponent {...this.props} /> ) } } const mapStateToProps = ({ auth }) => { return { authenticated: auth.isAuthenticated } } return connect(mapStateToProps)(Authentication) }

Lo usas así:

import requireAuth from ''../HOC/require_auth'' class RestrictedArea extends Component { // ... normal view component } //map state to props export default connect(mapStateToProps, actions)(requireAuth(RestrictedArea))

Ahí, eso es todo lo que deseo que alguien me haya contado y mostrado.

TLDR Los archivos nav_reducer.js y nav_reducer.js son absolutamente los más importantes para hacerlo bien. El resto es viejo y familiar. Mis ejemplos deberían acelerarlo en una máquina de productividad salvaje.

[Editar] Aquí está mi creador de acción de cierre de sesión. Le resultará muy útil si desea borrar su pila de navegación para que el usuario no pueda presionar el botón Atrás del hardware de Android y volver a una pantalla que requiere autenticación:

//LOGOUT export const onLogout = (navigation) => { return async (dispatch) => { try { await AsyncStorage.removeItem(''token'') navigation.dispatch({ type: ''Navigation/RESET'', index: 0, actions: [{ type: ''Navigate'', routeName: ''Login'' }] }) return dispatch({ type: LOGOUT }) } catch (errors) { // pass the user through with no error // this restores INITIAL_STATE (see login_reducer.js) return dispatch({ type: LOGOUT }) } } } // login_reducer.js case LOGOUT: { return { ...INITIAL_STATE, isAuthenticated: false, } }

[edición de bonificación] ¿Cómo navego desde un Stack Navigator secundario a un Stack Navigator principal?

Si desea navegar desde uno de los navegadores de pila de su hijo y restablecer la pila, haga lo siguiente:

  1. Estar dentro de un componente agregando código, donde tenga this.props.navigation disponible
  2. Hacer un componente como <Something />
  3. Pase la navegación hacia él, así: <Something navigation={this.props.navigation} />
  4. Ir al código para ese componente
  5. Observe cómo tiene this.props.navigation disponible dentro de este componente secundario
  6. Ahora que ha terminado, simplemente llame a this.props.navigation.navigate(''OtherStackScreen'') y debería ver React Native mágicamente ir allí sin problema

Pero, quiero RESTABLECER toda la pila mientras navego a una pila principal.

  1. Llame a un creador de acciones o algo como esto (comenzando desde el paso 6): this.props.handleSubmit(data, this.props.navigation)
  2. Entra en el creador de la acción y observa este código que podría estar allí:

actionCreators.js

// we need this to properly go from child to parent navigator while resetting // if you do the normal reset method from a child navigator: this.props.navigation.dispatch({ type: ''Navigation/RESET'', index: 0, actions: [{ type: ''Navigate'', routeName: ''SomeRootScreen'' }] }) // you will see an error about big red error message and // screen must be in your current stack // don''t worry, I got your back. do this // (remember, this is in the context of an action creator): import { NavigationActions } from ''react-navigation'' // notice how we passed in this.props.navigation from the component, // so we can just call it like Dan Abramov mixed with Gandolf export const handleSubmit = (token, navigation) => async (dispatch) => { try { // lets do some operation with the token await AsyncStorage.setItem(''token@E1'', token) // let''s dispatch some action that doesn''t itself cause navigation // if you get into trouble, investigate shouldComponentUpdate() // and make it return false if it detects this action at this moment dispatch({ type: SOMETHING_COMPLETE }) // heres where it gets 100% crazy and exhilarating return navigation.dispatch(NavigationActions.reset({ // this says put it on index 0, aka top of stack index: 0, // this key: null is 9001% critical, this is what // actually wipes the stack key: null, // this navigates you to some screen that is in the Root Navigation Stack actions: [NavigationActions.navigate({ routeName: ''SomeRootScreen'' })] })) } catch (error) { dispatch({ type: SOMETHING_COMPLETE }) // User should login manually if token fails to save return navigation.dispatch(NavigationActions.reset({ index: 0, key: null, actions: [NavigationActions.navigate({ routeName: ''Login'' })] })) } }

Estoy usando este código dentro de una aplicación React Native de nivel empresarial, y funciona de maravilla.

react-navigation es como la programación funcional. Está diseñado para ser manejado en pequeños fragmentos de "navegación pura" que se componen bien juntos. Si emplea la estrategia descrita anteriormente, se encontrará creando una lógica de navegación reutilizable que puede pegar según sea necesario.

Estoy tratando de usar react-navigation para crear una pantalla INICIAR SESIÓN inicial que no tiene barra de pestañas ni encabezado, y una vez que el usuario se haya autenticado correctamente, navegará a otra pantalla llamada LISTRECORD que tiene una barra de pestañas, encabezado y ninguna opción de botón de retroceso. ¿Alguien tiene experiencia en esto y puede compartir?

En resumen, lo que estoy tratando de lograr con react-navigation se describe a continuación ...

Pantalla 1: pantalla de inicio de sesión (sin encabezado y barra de pestañas)
Autenticado ...
Pantalla 2: LISTRECORD (encabezado, barra de pestañas y sin botón de retroceso)
La barra de pestañas contiene otras pestañas también para navegar a la Pantalla 3, Pantalla 4 ...


Necesitaba esto, pero ninguna de las otras soluciones funcionó para mí. Así que aquí está mi solución para un inicio de sesión con un cajón (este último accesible solo después de la autenticación adecuada, y cada una de las pantallas dentro tiene su propia pila de navegación). Mi código tiene un DrawerNavigator, pero el mismo podría usarse para un TabNavigator (createBottomTabNavigator).

wrapScreen = stackNavigator => createStackNavigator(stackNavigator, { defaultNavigationOptions: ({ navigation }) => ({ headerStyle: { backgroundColor: "white" }, headerLeft: MenuButton(navigation) }) }); const DrawerStack = createDrawerNavigator( { // Menu Screens firstSection: wrapScreen({ FirstScreen: FirstScreen }), secondSection: wrapScreen({ SecondHomeScreen: SecondHomeScreen, SecondOptionScreen: SecondOptionScreen }), settingSection: wrapScreen({ SettingScreen: SettingScreen }), aboutSection: wrapScreen({ AboutScreen: AboutScreen }) }, { initialRouteName: "firstSection", gesturesEnabled: false, drawerPosition: "left", contentComponent: DrawerContainer } ); const PrimaryNav = createSwitchNavigator( { loginStack: LoginScreen, appStack: DrawerStack }, { initialRouteName: "loginStack" } ); export default createAppContainer(PrimaryNav);

Espero que pueda ayudar a otros.



Así es como logré esta funcionalidad.

Archivo 0) index.android.js

''use strict'' import React, { Component } from ''react''; import { AppRegistry, StyleSheet, Text, View } from ''react-native''; import Root from ''src/containers/Root'' AppRegistry.registerComponent(''Riduk'', () => Root);

Archivo 1) mi Root.js

class Root extends Component { constructor(props) { super(props); this.state = { authenticated:false, isLoading:true, store: configureStore(() => this.setState({isLoading: false})), }; } componentDidMount() { //you can do check with authentication with fb, gmail and other right here /* firebase.auth().onAuthStateChanged((user) => { if (user) { api.resetRouteStack(dispatch, "UserProfile"); console.log("authenticated", user); } else { api.resetRouteStack(dispatch, "Landing"); console.log("authenticated", false); } });*/ } render() { if (this.state.isLoading) { //checking if the app fully loaded or not, splash screen can be rendered here return null; } return ( <Provider store={this.state.store}> <App/> </Provider> ); } } module.exports = Root;

2) App.js

import AppWithNavigationState,{AppBeforeLogin} from ''./AppNavigator''; class App extends Component{ constructor(props){ super(props); } render(){ let {authenticated} = this.props; if(authenticated){ return <AppWithNavigationState/>; } return <AppBeforeLogin/> } } export default connect(state =>({authenticated: state.user.authenticated}))(App);

3) AppNavigator.js

''use strict''; import React, {Component} from ''react''; import { View, BackAndroid, StatusBar,} from ''react-native''; import { NavigationActions, addNavigationHelpers, StackNavigator, } from ''react-navigation''; import { connect} from ''react-redux''; import LandingScreen from ''src/screens/landingScreen''; import Login from ''src/screens/login'' import SignUp from ''src/screens/signUp'' import ForgotPassword from ''src/screens/forgotPassword'' import UserProfile from ''src/screens/userProfile'' import Drawer from ''src/screens/drawer'' const routesConfig = { //Splash:{screen:SplashScreen}, Landing:{screen:LandingScreen}, Login: { screen: Login }, SignUp: { screen: SignUp }, ForgotPassword: { screen: ForgotPassword }, UserProfile:{screen:UserProfile}, }; export const AppNavigator = StackNavigator(routesConfig, {initialRouteName:''UserProfile''}); //navigator that will be used after login

export const AppBeforeLogin = StackNavigator (routesConfig); // naviagtor para antes de iniciar sesión

class AppWithNavigationState extends Component{ constructor(props) { super(props); this.handleBackButton = this.handleBackButton.bind(this); } componentDidMount() { BackAndroid.addEventListener(''hardwareBackPress'', this.handleBackButton); } componentWillUnmount() { BackAndroid.removeEventListener(''hardwareBackPress'', this.handleBackButton); } //added to handle back button functionality on android handleBackButton() { const {nav, dispatch} = this.props; if (nav && nav.routes && nav.routes.length > 1) { dispatch(NavigationActions.back()); return true; } return false; } render() { let {dispatch, nav} = this.props; return ( <View style={styles.container}> {(api.isAndroid()) && <StatusBar backgroundColor="#C2185B" barStyle="light-content" /> } <AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav })}/> </View> ); } }; export default connect(state =>({nav: state.nav}))(AppWithNavigationState); //module.exports = AppWithNavigationState;


Aunque lo que sugiere Manjeet funcionará, no es una buena estructura de navegación.

Lo que debe hacer es dar un paso atrás y manejar todo en otro nivel.

El navegador de nivel superior debe ser un navegador de pila que muestre una pantalla de inicio de sesión. Otra pantalla dentro de este navegador superior debería ser el navegador principal de su aplicación. Cuando se satisface su estado de inicio de sesión, restablece la pila principal solo al navegador principal.

La razón de esta estructura es:

A- ¿Qué sucede si necesita agregar información de incorporación antes de iniciar sesión en el futuro?

B- ¿Qué sucede si necesita navegar fuera del entorno de navegación principal (por ejemplo: su navegación principal son pestañas y desea una vista sin pestañas)?

Si su navegador superior es un navegador de pila que presenta pantallas de inicio de sesión y otros navegadores, entonces la estructura de navegación de su aplicación puede escalar adecuadamente.

No creo que la representación condicional de una pantalla de inicio de sesión o un navegador de pila, como se sugirió anteriormente, sea una buena idea ... créanme ... He seguido ese camino.


Es bueno que esté utilizando react-navigation que tiene un buen soporte para la mayoría de las funciones que requiere su aplicación. Heres mi consejo

1) En autenticación

React-native tiene esta agradable característica de variables de estado que cuando se cambian las vistas se vuelven a representar. Puede usar variables de estado para comprender el "estado" (autenticado / visitante) de los usuarios de su aplicación.

Aquí hay una implementación simple donde un usuario inicia sesión presionando un botón de inicio de sesión

Página de entrada donde el usuario inicia sesión

import React from ''react''; import Home from ''./layouts/users/home/Home''; import Login from ''./layouts/public/login/Login''; class App extends React.Component { state = { isLoggedIn: false } componentDidMount() { //Do something here like hide splash screen } render(){ if (this.state.isLoggedIn) return <Home />; else return <Login onLoginPress={() => this.setState({isLoggedIn: true})} />; } } export default App;

2) Iniciar sesión con encabezado

Vista de inicio de sesión

import React from ''react''; //Non react-native import import { TabNavigator } from ''react-navigation'' import Icon from ''react-native-vector-icons/MaterialIcons'' import LoginStyles from ''./Style'' //Do all imports found in react-native here import { View, Text, TextInput, StyleSheet, TouchableOpacity, } from ''react-native''; class Login extends React.Component { render(){ return ( <View> <Text> Login area </Text> <TouchableOpacity style={LoginStyles.touchable} onPress={this.props.onLoginPress} > <Text style={LoginStyles.button}> Login </Text> </TouchableOpacity> </View> ); } } export default Login;

Recuerde eliminar los atributos de estilo en la pantalla de inicio de sesión y agregar los suyos, incluida la importación, los dejo allí, ya que puede ayudarlo a tener una idea de cómo puede organizar su proyecto de reacción

Sin embargo, todavía funciona sin los estilos, por lo que puede quitarlos, al hacer clic en el botón de inicio de sesión lo llevará a la pantalla de Inicio, ya que el estado cambió y la vista debe volver a representarse según el nuevo estado

La pantalla de inicio de sesión no tiene un encabezado como lo requirió

Pantalla de inicio con pestañas

3) Pestañas con encabezado El método general para lograr esta funcionalidad es agregar un TabNavigator en un StackNavigator .

import React from ''react''; import { DrawerNavigator, StackNavigator, TabNavigator, TabBarBottom, NavigationActions } from ''react-navigation'' import Icon from ''react-native-vector-icons/MaterialIcons'' //Do all imports found in react-native here import { View, Text, TextInput, StyleSheet, TouchableOpacity, } from ''react-native''; class PicturesTab extends React.Component { static navigationOptions = { tabBarLabel: ''Pictures'', // Note: By default the icon is only shown on iOS. Search the showIcon option below. tabBarIcon: ({ tintColor }) => (<Icon size={30} color={tintColor} name="photo" />), }; render() { return <Text>Pictures</Text> } } class VideosTab extends React.Component { static navigationOptions = { tabBarLabel: ''Videos'', tabBarIcon: ({ tintColor }) => (<Icon size={30} color={tintColor} name="videocam" />), }; render() { return <Text>Videos</Text> } } const HomeTabs = TabNavigator({ Pictures: { screen: PicturesTab, }, Videos: { screen: VideosTab, }, }, { tabBarComponent: TabBarBottom, tabBarPosition: ''bottom'', tabBarOptions: { //Thick teal #094545 activeTintColor: ''#094545'', showLabel: false, activeBackgroundColor: ''#094545'', inactiveTintColor: ''#bbb'', activeTintColor: ''#fff'', } }); const HomeScreen = StackNavigator({ HomeTabs : { screen: HomeTabs, navigationOptions: ({ navigation }) => ({ // title :''title'', // headerRight:''put some component here'', // headerLeft:''put some component here'', headerStyle: { backgroundColor: ''#094545'' } }) }, }); export default HomeScreen;

Descargo de responsabilidad: el código puede devolver errores, ya que pueden faltar algunos archivos o algunos errores tipográficos, debe verificar los detalles cuidadosamente y cambiar dónde sea necesario si tiene que copiar este código. Cualquier problema puede ser pegado como comentarios. Espero que esto ayude a alguien.

¡También puede eliminar los íconos en las configuraciones de las pestañas o instalar los íconos react-native-vector que hacen que las pestañas sean geniales!


Esta es mi solución basada en la recomendación de @parker :

  1. Cree un navegador de nivel superior y debe ser un navegador de pila que muestre una pantalla de inicio de sesión.
  2. Otra pantalla dentro de este navegador de nivel superior debería ser el navegador principal de su aplicación.
  3. Cuando se satisface su estado de inicio de sesión, restablece la pila principal solo al navegador principal.

Este código hace lo mínimo para lograr lo anterior.

Cree un nuevo proyecto react-native, luego copie el siguiente código en index.ios.js y / o index.android.js para verlo funcionando.

import React, { Component } from ''react''; import { AppRegistry, Text, Button } from ''react-native''; import { StackNavigator, NavigationActions } from ''react-navigation''; const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: ''Main'' }) ] }); class LoginScreen extends Component { login() { this.props.navigation.dispatch(resetAction); } render() { return <Button title=''Login'' onPress={() => {this.login()}} />; } } class FeedScreen extends Component { render() { return <Text>This is my main app screen after login</Text>; } } //Create the navigation const MainNav = StackNavigator({ Feed: { screen: FeedScreen }, }); const TopLevelNav = StackNavigator({ Login: { screen: LoginScreen }, Main: { screen: MainNav }, }, { headerMode: ''none'', }); AppRegistry.registerComponent(''ReactNav2'', () => TopLevelNav);


Haga que la barra de pestañas y el encabezado separen los componentes y solo los incluya en otros componentes. Sobre la desactivación de "ATRÁS", hay una sección sobre "bloqueo de acciones de navegación" en los documentos: https://reactnavigation.org/docs/routers/

Debería poder usar eso para la pantalla 2.


Sé que soy viejo aquí, pero este artículo me salvó el trasero, estoy en el infierno con la navegación y ahora me siento más cómodo.

Ese tipo está explicando la API interna que le permitirá construir su navegación exactamente como se imagina , utilizando también un navegador de pila principal.

Se profundiza con un ejemplo de autenticación

https://hackernoon.com/a-comprehensive-guide-for-integrating-react-navigation-with-redux-including-authentication-flow-cb7b90611adf

Aplauda a este chico :-)


Si no desea un botón de retroceso desde su página LISTA a la página INICIAR SESIÓN, puede hacer esto:

static navigationOptions = { title: ''YOUR TITLE'', headerLeft : null, };


react-navigation ahora tiene un SwitchNavigator que ayuda al comportamiento deseado y al cambio entre navegadores. Actualmente no hay mucha documentación al respecto, pero hay un muy buen ejemplo de snack creado por la biblioteca que muestra una implementación de flujo de autenticación simple. Puedes consultarlo here .

Referencia de SwitchNavigator

SwitchNavigator(RouteConfigs, SwitchNavigatorConfig)

Ejemplo de documentos

const AppStack = StackNavigator({ Home: HomeScreen, Other: OtherScreen }); const AuthStack = StackNavigator({ SignIn: SignInScreen }); export default SwitchNavigator( { AuthLoading: AuthLoadingScreen, App: AppStack, Auth: AuthStack, }, { initialRouteName: ''AuthLoading'', } );