React Navigation 3-传奇内幕

时间:2019-06-11 23:24:37

标签: react-native react-navigation expo redux-saga

我正在开发一个使用redux-sagas和react-navigation v3的应用程序。

我现在面临的问题是我想在传奇中使用导航方法。该操作实际上已调度,我可以在记录器中看到它,但它不会更改我的屏幕。

这是我的文件:

App.js

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux';
import store from './store';
import Navigator from './routes/index.js'

export default function App() {
  return (
    <Provider store={store}>
      <Navigator />
    </Provider>
  );
}

routes.js

import React from "react";
import { View, Text } from "react-native";
import {
  createBottomTabNavigator,
  createSwitchNavigator,
  createStackNavigator,
  createAppContainer
} from "react-navigation";

import { FontAwesome } from '@expo/vector-icons';

// Screens
import LoginScreen from '../screens/Login.js';

// Routes
import Leads from './leads.js';
import Settings from './settings.js';


const TabsStack = createBottomTabNavigator(
  {
    Leads: Leads ,
    Settings: Settings,
  },
  {
    defaultNavigationOptions: ({ navigation }) => ({
      tabBarIcon: ({ focused, horizontal, tintColor }) => {
        const { routeName } = navigation.state;
        const iconSize = 28;
        let iconName;
        if (routeName === 'Leads') {
          iconName = 'home'
        } else if(routeName === 'Settings'){
          iconName = 'cogs'
        }

        return <FontAwesome name={iconName} size={iconSize} color={tintColor} />
      },
    }),
    tabBarOptions: {
      activeTintColor: '#208DFF',
      inactiveTintColor: '#cecece',
      showLabel: false
    },
  }
);

const LoginStack = createStackNavigator({
  Login: {
    screen: LoginScreen,
    navigationOptions: ({navigation}) => ({
      header: null
    })
  }
});

const Router = createSwitchNavigator(
  {
    Login: LoginStack,
    Tabs: TabsStack,
  },
  {
    initialRouteName: "Login"
  }
);


export default createAppContainer(Router);

store.js

import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from "redux-saga";
import { createLogger } from 'redux-logger';
import sagas from '../sagas/';
import reducers from '../reducers/';

const sagaMiddleware = createSagaMiddleware();
const loggerMiddleware = createLogger({collapsed: true});

const store = createStore(
  reducers,
  applyMiddleware(sagaMiddleware, loggerMiddleware)
);

sagaMiddleware.run(sagas);

export default store;

最后是我的传奇

import { takeLatest, call, put } from "redux-saga/effects";

import { NavigationActions } from "react-navigation";
import * as sessionActions from '../actions/sessions';
import * as navigateActions from '../actions/navigation.js';
import { login } from '../api/index.js';
import { AsyncStorage } from 'react-native';

export function* loginRequest({email, password}){
  let response = yield call(login, {email, password})
  if(!response.error){
    saveToken(response.auth_token);
    yield put({type: sessionActions.SESSION_LOGIN_REQUEST_SUCCESS, user: response})
  }else{
    yield put({type: sessionActions.SESSION_LOGIN_REQUEST_FAILURE, error: response.error})
  }
}

export function* loginRequestSuccessful(){
  console.log("Teste! 2");
  yield put(NavigationActions.navigate({ routeName: 'Leads' }))
}

async function saveToken(token) {
  try {
    return await AsyncStorage.setItem("auth_token", token);
  } catch (err) {
    console.error(err);
  }
}

function* loginSaga(){
  yield takeLatest(sessionActions.SESSION_LOGIN_REQUEST, loginRequest);
  yield takeLatest(sessionActions.SESSION_LOGIN_REQUEST_SUCCESS, loginRequestSuccessful);
}

export default loginSaga;

我是从记录器那里得到的

action Navigation/NAVIGATE @ 20:23:07.668
RemoteConsole.js:80  prev state {sessions: {…}}
RemoteConsole.js:80  action     {type: "Navigation/NAVIGATE", routeName: "Leads", @@redux-saga/SAGA_ACTION: true}
RemoteConsole.js:80  next state {sessions: {…}}

我不知道如何导航到sagas函数中的另一个屏幕。

导航工作的唯一方法是在组件内部使用this.props.navigation,但我需要在sagas内部进行工作。

1 个答案:

答案 0 :(得分:1)

在我的项目中,我按如下操作:

  • 第1步:像这样设置AppNavigationContainer的引用

AppContainer = createAppContainer(this.Switch);

  constructor(props: any) {
    super(props);
    this.state = {};
  }

  handleNavigationChange = (
    prevState: NavigationState,
    newState: NavigationState,
    action: NavigationAction,
  ) => {
  };

  render(): React.ReactNode {
    return (
      <Root>
        {/* <StatusBar barStyle="dark-content" /> */}
        <this.AppContainer
          ref={(navigatorRef: any) => {
            serviceProvider.NavigatorService().setContainer(navigatorRef);
          }}
          onNavigationStateChange={this.handleNavigationChange}
        />
      </Root>
    );
  }

  • 第2步:在this.AppContainer中添加由ref调用的导航服务

import { NavigationActions, NavigationParams, NavigationRoute, NavigationContainerComponent, NavigationContainer } from 'react-navigation';

export default class NavigatorService {
    container?: NavigationContainerComponent & NavigationContainer;

    setContainer = (container: NavigationContainerComponent & NavigationContainer): void => {
        this.container = container;
    }

    getContainer = (container: NavigationContainerComponent & NavigationContainer): any  => {
        return container;
    }

    navigate = (routeName: string, params?: NavigationParams): void => {
        if (this.container) {
            this.container.dispatch(
                NavigationActions.navigate({
                    routeName,
                    params,
                }),
            );
        }
    }

    goBack = (): void => {
        if (this.container) {
            this.container.dispatch(
                NavigationActions.back(),
            );
        }
    }

    getCurrentRoute(): NavigationRoute | null {
        if (!this.container || !this.container.state.nav) {
            return null;
        }
        return this.container.state.nav.routes[this.container.state.nav.index] || null;
    }

}

  • 第3步:在Saga中,您可以调用此按钮导航到所需的屏幕

serviceProvider.NavigatorService().navigate(//screenName)