结合React Navigation 3.0和JWT以根据身份验证状态确定initialRouteName

时间:2018-11-29 23:28:20

标签: react-native react-navigation

我正在尝试使与JWT客户端集成的普通App.js组件在集成React Navigator 3.0时能够正确运行

不幸的是,我只能使一个工作或另一个工作,而不能两者兼而有之。我的问题是,React Navigator会劫持App.js,并确定初始路径,而不是通常的App组件渲染。

到目前为止,这是我的代码:

App.js

import React, { Component } from 'react';
import { createAppContainer,
         createBottomTabNavigator,
        } from 'react-navigation';
import Auth from './src/screens/Auth';
import HomeScreen from './src/screens/HomeScreen';

class App extends Component {
  constructor() {
    super();
    this.state = {
      jwt: '',
    };
  }

  render() {
     if (!this.state.jwt) {
      return (
        <Auth />
      );
    } else if (this.state.jwt) {
      return (
        <HomeScreen />
      );
    }
  }
}

const TabNavigator = createBottomTabNavigator({
  Home: { screen: HomeScreen,
          navigationOptions: {
            tabBarLabel: 'Home',
          }
        },
  Auth: { screen: Auth,
          navigationOptions: {
            tabBarLabel: 'Auth',
          }
        },
  },
  { initialRouteName: App.state.jwt ? 'Home' : 'Auth' }
);

export default createAppContainer(TabNavigator);

如您所见,我的问题是此行:

{ initialRouteName: App.state.jwt ? 'Home' : 'Auth' }

如何获取TabNavigator组件内的JWT状态,以便定义正确的initialRouteName?

this.state.jwtApp.state.jwt显然不起作用,我尝试(失败了)将状态作为道具传递给TabNavigator对象。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

这是正确的方法:

首先,您设置获取Auth令牌并将其状态保存在App.js中。然后,将状态screenProps传递给导航对象:

export default class App extends React.Component {

  constructor() {
    super();
    this.state = {
      jwt: '',
      loading: true
    };
    this.newJWT = this.newJWT.bind(this);
    this.deleteJWT = deviceStorage.deleteJWT.bind(this);
    this.loadJWT = deviceStorage.loadJWT.bind(this);
    this.loadJWT();
  }

  state = {
    isLoadingComplete: false,
  };

  newJWT(jwt) {
    this.setState({
      jwt: jwt
    });
  }

  render() {
    if (this.state.loading) {
      return (
        <Loading size={'large'} />
       );
    } else if (!this.state.jwt) {
      return (
        <View style={styles.container}>
          {Platform.OS === 'ios' && <StatusBar barStyle="default" />}
          <TabNavigator screenProps={{setToken: this.newJWT }} />
        </View>
      );
    }

导航对象将其传递到需要它的屏幕上。

const TabNavigator = createMaterialTopTabNavigator(
  {
  Profile: {
    screen: props => <ProfileScreen {...props.screenProps} />,
    navigationOptions: {
        //tabBarLabel: 'Perfil',
        title: 'Header Title',
        tabBarIcon: ({ tintColor, focused }) => (
      <Ionicons
        name={focused ? 'ios-person' : 'ios-person'} //TODO change to focused icon
        size={26}
        style={{ color: tintColor }}
      />
    ),
  }
  },

您可以看到道具可以作为ScreenProps传递,然后像下面这样读入子组件(屏幕):

export default class ProfileScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      email: '',
      username: '',
      phone: '',
      password: '',
      name: '',
      error: ''
    };
  }

  componentDidMount() {
    const headers = {
      Authorization: this.props.jwt
    };
    api.get('/user')
    .then((response) => {
      this.setState({
        email: response.data.data.attributes.email,
        phone: response.data.data.attributes.phone,
        username: response.data.data.attributes.username,
        name: response.data.data.attributes.name,
        loading: false
      });
    }).catch((error) => {
      this.setState({
        error: 'Error retrieving data',
        loading: false
      });
    });
  }

我想使用Redux会更简单,但是我仍在学习。

答案 1 :(得分:0)

请问您是否包括登录屏幕以进行身份​​验证?