react-navigation / rfcs

RFCs for changes to React Navigation
Other
88 stars 16 forks source link

dispatch: return a promise resolving on navigation animation completion #11

Closed slorber closed 6 years ago

slorber commented 6 years ago

Hi,

I'd like to dispatch a navigation event, and only once the navigation has completed, perform some side-effect.

As the navigation may be animated, I can't just do this:

navigation.dispatch(action);
showSomething();

Otherwise the thing I want to show will be displayed before animation completes, leading to unexpected flicker.

I think due to the async/animated nature of the navigation, dispatching could return a promise, so that I can do:

navigation.dispatch(action).then(() => {
  showSomething();
});

Currently dispatch return a boolean. I guess this would be a breaking change and the boolean is maybe used as BackHandler return value?

brentvatne commented 6 years ago

you could wrap dispatch with a fn that adds a listener for didBlur and then resolves the promise and removes itself

dantman commented 6 years ago

The dispatch API is based on Redux. And When Redux is React Navigation's dispatch method is 100% replaced with the standard Redux dispatch method. So we cannot change the dispatch API to return a Promise.

Something similar to React Native's InteractionManager.runAfterInteractions but for transitions would probably work better.

I think I had more concrete API ideas in one of my comments on another issue.

slorber commented 6 years ago

Thanks will try to use did Blur.

With Redux you can easily return a promise from dispatch and it's actually common to do so, for example in thunks. Nothing forbids a Middleware to return something useful.

But I agree with the idea of a hook to wait for navigation completion. But maybe a singleton would not be appropriate and did Blur is already that?

Le 9 févr. 2018 06:09, "Daniel Friesen" notifications@github.com a écrit :

The dispatch API is based on Redux. And When Redux is React Navigation's dispatch method is 100% replaced with the standard Redux dispatch method. So we cannot change the dispatch API to return a Promise.

Something similar to React Native's InteractionManager.runAfterInteractions but for transitions would probably work better.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/react-navigation/rfcs/issues/11#issuecomment-364336749, or mute the thread https://github.com/notifications/unsubscribe-auth/AAtvPnGLmyT637txluili6l-6wUcA-fyks5tS9MRgaJpZM4R9BSN .

dantman commented 6 years ago

@slorber Oh, I'm still pre-middleware. Didn't see that things changed.

slorber commented 6 years ago

didBlur seems to work fine @brentvatne thanks

I've made a pr to the doc as it's not well documented: https://github.com/react-navigation/react-navigation.github.io/pull/54

slorber commented 6 years ago

this works fine:

goBackAsync = () => {
  const promise = new Promise(resolve => {
    const subscription = this.props.navigation.addListener('didBlur', () => {
      subscription.remove();
      resolve();
    });
  });
  this.props.navigation.goBack();
  return promise;
};
brentvatne commented 6 years ago

cool, closing this then!