Как объединить несколько задач при запуске приложения React Native

Я разрабатываю приложение на основе местоположения. Чтобы получить данные из API, мне нужны две вещи: позиция и, конечно же, подключение к Интернету.

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

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

Итак, я вижу несколько задач, которые необходимо выполнить при запуске:

  • Попробуйте получить GPS-позицию
  • Скрыть заставку
  • Если GPS-позиция недоступна, должно появиться модальное окно для входа в город.
  • Получение данных из API (требуется GPS-позиция и интернет)
  • Показать сообщение, что нет подключения к интернету

Я попытался поместить эти вещи в блок-схему, не принимая во внимание UML или стандарты. Может быть, это поможет понять, что я пытаюсь архивировать.

Блок-схема

Вопрос

1) Когда я должен инициировать получение данных? После запуска вы можете использовать кнопку Pull-To-Refresh или кнопку Retry для повторной загрузки. Но где это должно срабатывать при запуске? В ListContainer componentWillMount?

2) Как ждать с получением, пока есть позиция и подключение к интернету? редукс-сага?

Мой текущий подход использует redux-saga, но я не знаю, правильный ли это способ решить эту проблему...

Чтобы использовать redux-saga, я немного изменил свои действия, чтобы теперь их было три, для соответствующих действий саги: GPS_POSITION_RECEIVED, SET_POSITION (при установке позиции в LocationModal) и INTERNET_AVAILABLE. Проблема в том, что я не могу ждать/предпринимать все действия, потому что GPS_POSITION_RECEIVED и SET_POSITION никогда не произойдут одновременно. GPS может быть получен навигатором или пользователь выбирает его самостоятельно.

import { take, put, call, fork, select, all } from 'redux-saga/effects'

export function* init() {
  try {
    // Wait for the position
    console.log('Start init...');
    console.log('Wait for position and internet...')
    const posAndInet = yield take(['GPS_POSITION_RECEIVED', 'INTERNET_AVAILABLE']);
    console.log('Position and internet ready...');

    // Fetch data now
    // ....
  } catch (e) {
    console.error(e);
  }
}

export default function* rootSaga() {
  yield[
    fork(init),
  ];
}

И еще есть несколько функций, которые я запускаю в componenWillMount() App-компонента. Может с Сагой или вообще есть места получше?

  if(Platform.OS == 'android') StatusBar.setBackgroundColor('#000');

  // Push Notifications
  OneSignal.addEventListener('registered', () => {
    // Track it to Google Analytics
    this.props.registeredPushNotifications();
  });

  OneSignal.addEventListener('ids', (device) => {
    // Save
    this.props.receivedPlayerId(device.userId);
  });

  // Trigger watch position
  this.props.watchPosition();

  // Trigger internet connection oberservation
  this.props.watchInternetConnection();

  setTimeout(SplashScreen.hide, 1000);

person rakete    schedule 05.11.2017    source источник


Ответы (2)


Два пути:

  1. Без Redux — поместите логику инициализации в правильную функцию Component componentDidMount
  2. С Redux — используйте пакет Redux-Saga и следите за INITIALIZE. действие отправляется сразу после инициализации хранилища.
person Alexander Vitanov    schedule 05.11.2017
comment
Я использую редукс. Сага выглядит действительно интересно.. Я должен попытаться понять это... - person rakete; 05.11.2017

я не использовал redux-saga, поэтому на вашем месте я бы решил это так, actiontypes.js

export const APP_TASK_STATE="APP_TASK_STATE";

создайте свойство в редукторе task_state, значение которого как перечисление

 start //as default,
 clean // all is clean  do after this tasks 
 splash // show splash screen 
 gps-modal // show gps modal 
 no-internet / for no internet 

редуктор.js

  let newState = Object.assign({}, state); 
    if(action.type===""APP_TASK_STATE"){

      newState.task_state=action.payload;

     return newState;  
   }

действия.js

import * as Actions from './actiontypes';

//Task States  Handler 
export function taskState(state) {
    return { type: Actions.APP_TASK_STATE, payload: state };
}


export function readGps() {
    return (dispatch) => {
        dispatch(taskState('splash'));
        //i dont know how do you get  gps  but i must be async i think 
        getGps()
            .then((val) => {
                dispatch(taskState('clean'));
                // your gps state success function
                dispatch(yourgpsSuccesFunction(val));

            }).catch((e) => {
                dispatch(taskState('gps-modal'));
                // maybe you can show message or something
                dispatch(showMessage(e));
            });
    }
}
// After entering modal city name
export function fetchApi(city) {
    return (dispatch) => {
        dispatch(taskState('splash'));
        fetch().then((val) => {
            dispatch(taskState('clean'));
        }).catch((e) => {
            dispatch(taskState('no-internet'));
        });
    }
}

вызвать readGps на componentWillMount()

использовать регистр переключателей на редукторах task_state при рендеринге

надеюсь, это поможет

person Saltuk    schedule 11.11.2017