Expo Standalone with Cloud Firestore (web SDK) Responses Take a Really Long time

For anyone that runs into this issue, this is my very horrible (but functional) workaround. First, create an app state listener on your component like so:

export default class App extends Component {
  state = {
    appState: AppState.currentState
  };

  store = store;

  componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);
    firebase.initializeApp(FIREBASE_DEVELOPMENT_CONFIG);

    firebase.auth().onAuthStateChanged(user => {

      if (!_.isNull(user)) {
        this.user = user;
        return this.store.dispatch(userChangedListener(user));
      }

      return this.store.dispatch(noUser());
    });
  }

  _handleAppStateChange = nextAppState => {
    if (
      this.state.appState.match(/inactive|background/) &&
      nextAppState === 'active'
    ) {
      this.store.dispatch(getUser());
    }
    this.setState({ appState: nextAppState });
  };

  componentWillUnmount() {
    AppState.removeEventListener('change', this._handleAppStateChange);
  }

  render() {
    return (
      <Provider store={this.store}>
        <ThemeProvider theme={theme}>
          <TopLevelNavigator />
        </ThemeProvider>
      </Provider>
    );
  }
}

Then spin up a cloud function or express instance that gets the query you are looking for once.
index.ts

...
import { getUser } from './getUser';

app.get('/get-user', getUser);

getUser.ts (server side)

import { db } from './utils/store';

export const getUser = async (req, res) => {
  const { user_id } = req.user;

  const userRef = db.collection('users').doc(user_id);
  const userQuery = await userRef.get();
  const user = userQuery.data();

  res.send(user);
};

Then you need to call that in a Redux action creator

export const getUser = user => async (dispatch, getState) => {
  dispatch({
    type: SHOW_LOADING,
    loading: true
  });

  try {
    let token = await firebase
      .auth()
      .currentUser.getIdToken(/* forceRefresh */ true);

    try {
      const config = {
        headers: {
          Authorization: `Bearer ${token}`,
          Accept: 'application/json'
        }
      };

      let response = await axios.get(`${FIREBASE_API_URL}/get-user`, config);

      dispatch({
        type: USER_CHANGED_LISTENER,
        userLoggedIn: true,
        payload: response.data
      });

      dispatch({
        type: HIDE_LOADING,
        loading: false
      });
    } catch (error) {
      dispatch(
        createErrorAction(CLOUD_FUNCTIONS_ERROR, error.response, 'high')
      );
    }
  } catch (error) {
    dispatch(createErrorAction(UNKNOWN_ERROR, error, 'high'));
  }
};

Dispatch to the same reducer so that way when someone opens your app the state is immediately re-rendering from the one time Express request. Then, about 30 seconds later your onSnapshot listener will start working again! :upside_down_face: