Подтвердить что ты не робот

React-Navigation с окном входа в систему

Я пытаюсь использовать интерактивную навигацию для создания начального экрана LOGIN, у которого нет заголовка и заголовка, и как только пользователь успешно прошел проверку подлинности, он перейдет на другой экран под названием LISTRECORD, у которого есть кнопка, заголовок и кнопка обратной кнопки, Кто-нибудь имеет опыт в этом и может делиться?

Вкратце, то, что я пытаюсь достичь с помощью интерактивной навигации, описано ниже...

Экран 1: Экран входа (без заголовка и табуляции)
Заверенные...
Экран 2: LISTRECORD (заголовок, вкладка и кнопка "Нет возврата" )
На вкладке также есть другие вкладки для навигации к Экран 3, Экран 4...

4b9b3361

Ответ 1

Oct 2017 Я нашел это смехотворно запутанным, так что вот мое решение, начиная сверху:

Я рекомендую начать новый проект и буквально просто вставить все это и изучить его после. Я прокомментировал код большого времени, поэтому, если вы застряли в какой-либо конкретной области, возможно, контекст может помочь вам вернуться в нужное русло.

Это сообщение показывает, как:

  1. полностью настроить React Native для запуска интерактивной навигации
  2. Правильно интегрируйте с Redux
  3. Обращайтесь к кнопке Android Back
  4. Nest Stack Navigators
  5. Перемещение с родительских навигаторов от родителя
  6. Сброс навигационного стека
  7. Сброс навигационного стека при переходе от дочернего к родительскому (вложенному)

index.js

import { AppRegistry } from 'react-native'
import App from './src/App'

AppRegistry.registerComponent('yourappname', () => App)

src/App.js (это самый важный файл, потому что он объединяет все клочки)

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 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

ЦСИ/навигация /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
}

ЦСИ/магазин /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/компоненты/аутентификации /SignUpForm.js

Здесь я покажу вам образец. Это не мое, я просто напечатал его для вас в этом рискованном редакторе StackOverflow. Пожалуйста, дайте мне большие пальцы, если вы оцените это :)

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/компоненты/аутентификации /LoginForm.js

Я покажу вам тупой стиль, также с кнопкой супер-допинга

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/компоненты/Авт/Splash.js

Вот заставка, с которой вы можете поиграть. Я использую его как компонент более высокого порядка:

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/компоненты/аутентификации /login_actions.js

Я просто покажу вам initializeApp(), чтобы вы получили некоторые идеи:

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
    }
}

В других вариантах использования вы можете предпочесть компонент более высокого порядка. Они работают точно так же, как React for web. Учебники Stephen Grider по Udemy - лучший, период.

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)
}

Вы используете его так:

import requireAuth from '../HOC/require_auth'

class RestrictedArea extends Component {
    // ... normal view component
}

//map state to props

export default connect(mapStateToProps, actions)(requireAuth(RestrictedArea))

Вот, это все, что я хочу, чтобы кто-то сказал и показал мне.

TL;DR App.js и nav_reducer.js абсолютно важны для правильного. Остальное - старый знакомый. Мои примеры должны ускорить вас в машине с дикой производительностью.

[Изменить] Вот мой создатель действия выхода. Вы найдете это очень полезным, если хотите стереть свой навигационный стек, чтобы пользователь не мог нажать кнопку Android Hardware Back и вернуться к экрану, требующему аутентификации:

//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,
        }
    }

[bonus edit] Как перейти от дочернего Stack Navigator к родительскому Stack Navigator?

Если вы хотите перейти от одного из ваших дочерних стековых навигаторов и сбросить стек, сделайте следующее:

  1. Будьте внутри кода добавления компонента, где у вас есть доступ к this.props.navigation
  2. Сделайте компонент вроде <Something/>
  3. Пройдите навигацию по нему, например: <Something navigation={this.props.navigation}/>
  4. Перейдите в код для этого компонента
  5. Обратите внимание, что у вас есть this.props.navigation доступно внутри этого дочернего компонента
  6. Теперь вы закончили, просто позвоните this.props.navigation.navigate('OtherStackScreen') и вы должны посмотреть, как React Native волшебным образом отправится туда без проблем

Но я хочу СБРОСИТЬ весь стек во время перехода к родительскому стеку.

  1. Вызвать создателя действия или что-то вроде этого (начиная с шага 6): this.props.handleSubmit(data, this.props.navigation)
  2. Идите в создателя действия и наблюдайте за этим кодом, который может быть там:

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('[email protected]', token)
        // let 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' })]
        }))
    }
}

Я использую этот код внутри корпоративного приложения React Native, и он работает красиво.

react-navigation походит на функциональное программирование. Он предназначен для обработки небольшими фрагментами "чистой навигации", которые хорошо сочетаются. Если вы используете стратегию, описанную выше, вы обнаружите, что создаете повторно используемую навигационную логику, которую вы можете просто вставлять по мере необходимости.

Ответ 2

Хотя то, что предлагает Манджейт, будет работать, это не хорошая навигационная структура.

Что вам нужно сделать, это сделать шаг назад и обработать все на другом уровне.

Навигатор верхнего уровня должен быть навигатором стека, который отображает экран входа в систему. Другой экран в этом самом верхнем навигаторе должен быть вашим основным навигатором. Когда ваше состояние входа будет удовлетворено, вы reset основного стека только к основному навигатору.

Причиной такой структуры является:

A- Что делать, если вам нужно добавить информацию о борде до входа в будущее?

B- Что делать, если вам нужно перемещаться за пределы среды Main-Navigation (например: ваш основной навигатор - это вкладки и вы хотите иметь представление без табуляции)?

Если ваш самый верхний навигатор - это Stack-Navigator, который отображает экраны входа и другие навигаторы, ваша структура навигации приложения может быть правильно масштабирована.

Я не считаю, что условная визуализация экрана входа или навигатора стека, как было предложено выше, является хорошей идеей... поверьте мне... Я пошел по этой дороге.

Ответ 3

так я достиг этой функциональности.

Файл 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);

Файл 1) my 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 для входа в систему

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;

Ответ 4

Это мое решение, основанное на рекомендации @parker:

  • Создайте навигатор верхнего уровня, и он должен быть навигатором стека, который отображает экран входа в систему.
  • Другой экран на этом верхнем уровне навигатором должно быть ваше приложение Main-Navigator.
  • Когда ваш логин состояние выполнено, вы reset основной стек только для Main-навигатор.

Этот код делает минимальный минимум для выполнения вышеуказанного.

Создайте новый проект, отвечающий за реакцию, затем скопируйте код ниже в index.ios.js и/или index.android.js, чтобы увидеть, как он работает.

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);

Ответ 5

Хорошо, что вы используете интерактивную навигацию, которая имеет хорошую поддержку большинства функций, которые требуется вашему приложению. Вот мой совет

1) Аутентификация

React-native имеет эту приятную переменную состояния функции, которая при изменении представлений повторно отображается. Вы можете использовать переменные состояния для понимания состояния (аутентифицированного/посетителя) пользователей вашего приложения.

Вот простая реализация, когда пользователь входит в систему, нажав кнопку входа в систему

Страница входа, где пользователь входит в систему

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) Войти с заголовком

Вход в систему

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;

Не забудьте удалить атрибуты стиля на экране входа в систему и добавить свои, включая импорт, я оставляю их там, так как это может помочь вам и понять, как вы можете организовать реакцию проекта

Однако он по-прежнему работает без стилей, поэтому вы можете снять их, нажав кнопку входа в систему, вы перейдете на главный экран, так как состояние изменилось и представление должно быть повторно отображено в соответствии с новым состоянием

Экран входа не имеет заголовка, как вам требуется

Начальный экран с вкладками

3) Вкладки с заголовком Общий способ достижения этой функциональности - добавить TabNavigator в 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;

Отказ от ответственности:. Код может возвращать ошибки, поскольку некоторые файлы могут отсутствовать или могут появляться какие-либо опечатки. Вы должны тщательно проверить данные и изменить их, если вам нужно скопировать этот код. Любые проблемы могут быть вставлены в виде комментариев. Надеюсь, это поможет кому-то.

Вы также можете удалить значки в настройках вкладки или установить значки "реагировать на корень", что делает вкладки великолепными!

Ответ 6

Создайте отдельные компоненты вкладки и заголовка и включите их только в другие компоненты. Об отключении "НАЗАД" в документах есть раздел о "блокировке действий навигации": https://reactnavigation.org/docs/routers/

Вы можете использовать это для экрана 2.

Ответ 7

react-navigation режиме SwitchNavigator react-navigation теперь есть SwitchNavigator который помогает желаемому поведению и переключению между навигаторами. В настоящее время документации о нем мало, но есть действительно хороший пример закуски, созданной библиотекой, которая показывает простую реализацию потока аутентификации. Вы можете проверить это здесь.

Ссылка SwitchNavigator

SwitchNavigator(RouteConfigs, SwitchNavigatorConfig)

Пример из документов

const AppStack = StackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = StackNavigator({ SignIn: SignInScreen });

export default SwitchNavigator(
  {
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'AuthLoading',
  }
);

Ответ 8

В настоящее время имеется хорошая документация на сайте по реагированию на аутентификацию.

Ответ 9

Если вы не хотите, чтобы с вашей страницы LIST на странице LOGIN не было возврата, вы можете сделать это:

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

Ответ 10

Мне это нужно, но ни одно из других решений не помогло мне. Итак, вот мое решение для входа в систему с выдвижным ящиком (последний доступен только после надлежащей аутентификации, и каждый из экранов внутри имеет свой собственный стек навигации). Мой код имеет DrawerNavigator, но то же самое можно использовать для 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);

Я надеюсь, что это может помочь другим.

Ответ 11

Я знаю, что я здесь уже старый, но эта статья спасла мою задницу, я в ад с навигацией, и теперь я чувствую себя более комфортно.

Этот парень объясняет внутренний API, который позволит вам строить навигацию так же, как вы себе представляете, используя также главный навигатор стека.

Он идет глубоко с примером аутентификации

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

Пожалуйста, хлопните этого парня :-)