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!