Реагируйте Навигация 3 - Вызов в Сага - PullRequest
0 голосов
/ 12 июня 2019

Я занимаюсь разработкой приложения, которое использует redux-sagas и response-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>
  );
}

rout.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 внутри компонента, но мне нужно работатьвнутри саг.

1 Ответ

1 голос
/ 12 июня 2019

В моем проекте я делаю это следующим образом:

  • Шаг 1: Установите ref для 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

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...