Откладывать уведомления о глубоких ссылках до тех пор, пока не будет полностью загружено приложение Exact-native expo. - PullRequest
0 голосов
/ 19 февраля 2020

Я бы хотел отложить событие навигации по глубоким ссылкам, привязанное к уведомлению, до тех пор, пока приложение не будет полностью загружено после того, как мое реагирующее родное приложение открывается при нажатии уведомления.

В настоящее время мой прослушиватель уведомлений находится в моем App.tsx файл. Глубокая связь работает, как и ожидалось, когда приложение работает в фоновом режиме, но когда уведомление запускает приложение, событие навигации запускается до того, как приложение сможет полностью загрузиться. Это означает, что, хотя я действительно глубоко привязан к правильному расположению, некоторые из моих активов еще не загружены, и мой лог авторизации c полностью обойден.

Есть ли способ, чтобы уведомление открывало приложение, но подождите, пока все не будет загружено (в частности, компонент AppLoading завершил выполнение своих функций), чтобы перейти к местоположению с глубокими ссылками? Я могу придумать какие-нибудь хакерские способы сделать это, но есть ли общепринятый шаблон, который обычно используется?

1 Ответ

0 голосов
/ 19 февраля 2020

Хорошо, поэтому я не уверен, что это лучший способ справиться с этим, но я нашел способ заставить мои уведомления работать.

(1) Я создал действие с именем registerAppLoaded и переменную состояния appLoaded, которую отправляю, как только мой компонент AppLoading завершит свои функции startAsync.

(2) Когда приходит уведомление, сначала я проверяю, истинно ли appLoaded. Если это так, я перехожу к пункту назначения, отправленному вместе с уведомлением. Если нет, я помещаю уведомление в магазин и продолжаю запускать приложение.

(3) в функции AppLoading onFinish, я проверяю, есть ли уведомление. Если это так, и он помечен new, я беру его и использую параметры для навигации. Затем я отправляю действие, которое устанавливает navigation.new = false

Кажется, работает именно так, как мне нужно!

Вот мой код, если кто-то еще имеет дело с этой проблемой:

App.tsx:

export default class App extends React.Component {

  componentDidMount() {
    Notifications.addListener((notification) => {
      if (notification.origin === "received") { 
        return; 
      } else {
        const appLoaded = store.getState().general.appLoaded
        if (appLoaded) {
          NavigationService.navigate(notification.data.navigate, {id:notification.data.id , shouldRefresh: true})
        } else {
          // save notification as new
          store.dispatch(addNotification(notification, true));
        }
      };
    })
  }

  render() {
    return (
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
          <View style={styles.container}>
            {Platform.OS === "ios" && <StatusBar barStyle="default" />}
            <ErrorBoundary backup={<AppError />}>
              <AppNavigator />
            </ErrorBoundary>
          </View>
        </PersistGate>
      </Provider>
    );
  }
}

AppLoading.tsx:

class AppLoadingScreen extends React.Component {
  _loadResourcesAsync = async() => {
    await this.props.fetchUserOnboarding(this.props.userId);
    if (this.props.userDevice && this.props.userDevice.id) {
      this.props.registerUserDevice(this.props.userId, this.props.userDevice.id)
    }
    // register that the app has finished loading in the store; this will be used to determine if a notification's deep 
    // link should be immediatedly navigated to or if the navigation even shuold be deferred until after the app 
    // finishes loading
    await this.props.registerAppLoaded()
  };

  _handleFinishLoading = async () => {
    // if a notification triggers the event listener but the app is not yet fully loaded, the deep link will be 
    // navigated to here instead of directly from the listener
    const notification = this.props.userNotifications && this.props.userNotifications[0]
    if (notification && notification.new && notification.origin != 'recieved') {
      this.props.addNotification(notification, false) // set notification.new = false
      this.props.navigation.navigate(notification.data.navigate, {id: notification.data.id, shouldRefresh: true})
    } else if (this.props.showGoalsPrompt) {
      this.props.navigation.navigate("Goal");
    } else {
      this.props.navigation.navigate("HomeFeed");
    }
  };

  render() {
    return (
      <AppLoading
        startAsync={this._loadResourcesAsync}
        onFinish={this._handleFinishLoading}
      />
    );
  }
}

actions.tsx:

export const registerAppLoaded = () => {
  return dispatch => {
    dispatch({
      type: types.REGISTER_APP_LOADED,
      payload: true
    });
  };
}

export const addNotification = (notification, isNew=false) => {
  return dispatch => {
    notification.new = isNew // indicate whether this is a new notification or if it has been seen
    dispatch({
      type:types.ADD_USER_NOTIFICATION,
      payload: notification,
    })
  };
}
...