React-native-router-flux: Race condition when quickly navigating between scenes

Created on 10 Oct 2016  路  15Comments  路  Source: aksonov/react-native-router-flux

Version

  • react-native-router-flux v3.35.0
  • react-native v0.34.1

    Expected behavior

* From someSceneA *
Actions.someSceneB(dataObj); -> yields the expected view with dataObj
* Android back button is pressed to return to someSceneA *
(quickly do:) Actions.someSceneB(otherDataObj); -> instantiates someSceneB with otherDataObj

Actual behavior

* From someSceneA*
Actions.someSceneB(dataObj); -> yields the expected view with dataObj
* Android back button is pressed to return to someSceneA *
(quickly do:) Actions.someSceneB(otherDataObj); -> re-renders someSceneB with dataObj

Current fix

It seems like what's happening above is a race condition, where if you try to navigate too quickly to a component that you've already been to, but with a new data object, it will not re-render that component with the new data. If you wait for a second for the animations to complete, the issue goes away.

In order to prevent the race condition described above, I'm doing:

    const onPress = () => {
      InteractionManager.runAfterInteractions(() => {
        Actions.someSceneB({ data });
      });
    };

Most helpful comment

I got this problem too. Tapping "back" button and then quickly tapping to another menu item rendered scene with previous props.

I did as @erikandersson suggested in a related issue:

<Router duration={150} ...>

It solved the problem! And it actually works for any value I tested between 50ms and 400ms, for some reason...

All 15 comments

Same issue here. Sometimes the dataObj is still the correct one here, but since I have some logic in the constructor/componentWillMount they are not called when quickly navigating to the same component as you described.

For me the InteractionManager "solves" it, but the user experience becomes worse in the sense that it takes longer until I can press something.

I also made a clean test project with nothing but react-native and react-native-router-flux and still had the same issue.

Almost same problem here.
scenario:
1) Actions.page1(); -> opens page 1
2) Back with android back button or with Action.pop();
3) Then opens Actions.page2() quickly -> i will see page1 for almost half second, then page 2 appears.

my guess is its happen when Action.pop() didnt finish yet.

Same problem here, component life cycle methods are not being called when quickly navigating between scenes.

guys, any luck now? It drives me crazy..

+1

+1

Looking through the source code, I believe the issues stems from the react-native NavigationExperimental component. There is a method handleNavigation that react-native-router-flux relies on. That method calls setState(), for navigation purposes. I believe the issue that is occurring is the result of the state change not being finished.

If handleNavigation could return the 2nd argument of setState() which is a callback when it's finished, we could use that to sync operations and avoid the race condition. Actions.pop() already returns the result of handleNavigation.

The problem obviously is that changing NavigationExperimental is not possible from this project, and I don't have the context for why handleNavigation was designed the way it is. So this issue may be fairly challenging to solve.

I will use @dannycochran 's solution for now.

+1

+1

This is driving me nuts.

Having the same issue where navigating too fast can have logic like Actions.refresh() in componentWillMount not being executed.

The InteractionManager.runAfterInteractions fixes the issue, however as others have stated, it does take longer until you can click something, or if the buttons and title elements even appear for that matter (if setting through Actions.refresh()).

I've found that defining a method such as onMount() in the component that contains your logic such as Actions.refresh() and then executing that method initially in componentWillMount and then with InteractionManager.runAfterInteractions() seems to act to cover the 90% of cases where my NavBar left and right buttons show initially when navigating, and then fallback when the race-condition is met, running again to make sure my user can actually navigate away through the NavBar.

Would be great for these component life cycle methods to be better handled when quickly navigating in the future!

p = new Promise((resolve, reject) => {
setTimeout(resolve, 10, 'foo');
});
p.then(()=> /* action.push first scene here /)
.then(()= /
action.push Second scene here */))

works like charm

IMO - as long as this library is using the forked version of RN ExerpimentalNavigation, that was forked almost a year ago, it's not a great decision to continue using this library. I don't fault the authors at all, it's really hard to maintain a library w/RN constantly changing its API.

I'm now using react-navigation, which has good community support and the API behaves pretty similarly to this one. Hopefully it'll be the last router based refactor I do for a while.

I'm closing this since it's unlikely to be fixed and there's a few workarounds. IMO the best workaround is moving to react-navigation.

I got this problem too. Tapping "back" button and then quickly tapping to another menu item rendered scene with previous props.

I did as @erikandersson suggested in a related issue:

<Router duration={150} ...>

It solved the problem! And it actually works for any value I tested between 50ms and 400ms, for some reason...

@vladimir-e This worked for me as well

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fgrs picture fgrs  路  3Comments

tonypeng picture tonypeng  路  3Comments

sarovin picture sarovin  路  3Comments

VictorK1902 picture VictorK1902  路  3Comments

maphongba008 picture maphongba008  路  3Comments