首页 > 解决方案 > 结合 React Navigation 3.0 和 JWT 根据身份验证状态确定 initialRouteName

问题描述

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

不幸的是,我只能做一个或另一个,而不是两者。我的问题是 React Navigator 有点劫持 App.js 并确定初始路线而不是通常的 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 对象。

任何帮助表示赞赏。

标签: react-nativereact-navigation

解决方案


这是正确的方法:

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

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 会简单得多,但我仍在学习。


推荐阅读