How to tell when a view will appear with ReactNavigation

MonkeyBonkey picture MonkeyBonkey · Apr 14, 2017 · Viewed 8.5k times · Source

I'm using ReactNavigation and am wondering how I can tell when a view will appear (so that I can trigger a data refresh). I see this example using a different navigator NavigatorIOS - Is there a viewDidAppear or viewWillAppear equivalent? but not sure how it would work with https://reactnavigation.org/.

I see the console.log on the navigation dispatches - but is there some event handler that I can hook into on the screen/component level to know if that component/screen is in the foreground? Should I hook into the getStateForAction method somehow? https://reactnavigation.org/docs/routers/api . I don't want to really create custom route handlers per se, just to detect if the view is entering foreground/will appear, and I'm guessing I can use the navigation event to do that somehow.

Answer

MonkeyBonkey picture MonkeyBonkey · May 23, 2017

So I got this working by creating a redux action and store that tracks the active screen and attaching it to the root navigation onNavigtionChange event.

      <RootNavigation
        ref={nav => { this.navigator = nav; }}
        onNavigationStateChange={(prevState, currentState) => {
          const currentScreen = this.getCurrentRouteName(currentState);
          const prevScreen = this.getCurrentRouteName(prevState);
          if (prevScreen !== currentScreen) {
            this.props.broadcastActiveScreen(currentScreen);
            {/*console.log('onNavigationStateChange', currentScreen);*/}
          }
        }}
      />

actions

import { createAction } from 'redux-actions';
import type { Dispatch } from '../state/store';

export const SCREEN_WILL_APPEAR = 'SCREEN_WILL_APPEAR';
const createScreenWillAppearAction = createAction(SCREEN_WILL_APPEAR);
export const broadcastActiveScreen = (activeScreen: string) => (
  (dispatch: Dispatch) => {
    dispatch(createScreenWillAppearAction(activeScreen));
  }
);

Reducer

export default handleActions({
  [SCREEN_WILL_APPEAR]: (state, action) => {
    return Object.assign({}, state, {
      activeScreen: action.payload,
    });
  },
}, initialState);

In the screen component

  componentWillReceiveProps(nextProps) {
    if (nextProps.activeScreen === 'MyScreenName' && nextProps.activeScreen !== this.props.activeScreen) {
     // put your on view will appear code here
    }
   }