Navigation Lifecycle

Cancelling Navigation

The onBeforeNavigate event gives you a chance to cancel a navigation. You're passed in details of the State being navigated to as well as a history flag that indicates whether the navigation was caused by the browser back button. In our email example, we can add an onBeforeNavigate listener that prompts the user to confirm they want to leave without sending their email.

componentDidMount() {
  this.beforeNavigate = function(state, data, url, history) {
    return history || confirm('You\'ve not sent your email. Continue?');
  }
  this.props.stateNavigator.onBeforeNavigate(this.beforeNavigate);
}

componentWillUnmount() {
  this.props.stateNavigator.offBeforeNavigate(this.beforeNavigate);
}

There's also an onNavigate event that fires after the navigation's happened. We could add an onNavigate listener that tracks page visits in our email app.

Fetching Data

You can intercept a navigation by attaching a function to the destination State's navigating property. This gives you a chance to suspend the navigation until an async operation, like data-fetching or code-splitting, completes. In the email example, when a user opens a mail we fetch the mail data inside a navigating function to avoid displaying a blank screen while the data loads. Once the data returns we pass it into the navigate continuation function.

stateNavigator.states.mail.navigating = function(data, url, navigate, history) {
  $.getJSON('api/mail/' + data.id, function(resp) {
    navigate({mail: resp});
  });
};

Update the Consumer's child render prop to pass this asynchronous data along in the second parameter of the call to the active State's renderView function.

<NavigationReact.NavigationContext.Consumer>
  {({ state, data, asyncData }) => state.renderView(data, asyncData)}
</NavigationReact.NavigationContext.Consumer>

The 'mail' State's renderView function passes the asynchronous mail data as a prop to the Mail component.

stateNavigator.states.mail.renderView = function(data, asyncData) {
  return <Mail mail={asyncData.mail} />;
};