Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screen loads twice when using TabNavigator #476

Closed
coreyt808 opened this issue Feb 24, 2017 · 66 comments
Closed

Screen loads twice when using TabNavigator #476

coreyt808 opened this issue Feb 24, 2017 · 66 comments

Comments

@coreyt808
Copy link

When using the TabNavigator the initial screen is loaded twice for some reason. This can be seen by adding an Alert or console.log in componentDidMount. I've replicated this in the SimpleTabs and StacksInTabs example. The SimpleStack example doesn't load twice.

const MyNavScreen = ({ navigation, banner }) => { Alert.alert(banner); return ( <ScrollView style={styles.container}> ....... </ScrollView> ); }

@arthurpark
Copy link

Try setting initialRouteName in TabNavigatorConfig. It fixed the issue for me.

@coreyt808
Copy link
Author

initialRouteName doesn't do anything for me.

I can confirm that this doesn't happen in the beta 5 release though. Will stick with beta 5 until this is fixed.

@makirby
Copy link

makirby commented Feb 27, 2017

Also having the same problem & initialRouteName has had no effect stopping it. Any idea what is causing it?

Happens in the examples project as well.

@makirby
Copy link

makirby commented Feb 27, 2017

Seems its introduced in the update to react-native-tabs in #366. I downgraded the lib to 0.0.55 and now it no longer mounts the component twice on initial load.

@ivpusic
Copy link

ivpusic commented Mar 1, 2017

I have the same issue

@grabbou
Copy link

grabbou commented Mar 1, 2017

cc: @satya164

@redgoose-dev
Copy link

same issue...

screen 2017-03-03 am 7 17 45

@f0rr0
Copy link

f0rr0 commented Mar 3, 2017

Same issue. Using beta-6

@grabbou
Copy link

grabbou commented Mar 3, 2017

Can any of you past the stack trace here? I'll try to fix it for the beta-7 for today's release.

@f0rr0
Copy link

f0rr0 commented Mar 3, 2017

@grabbou there is no error thrown anywhere

@despreston
Copy link

+1 for getting this into the beta 7 release !!

@grabbou
Copy link

grabbou commented Mar 3, 2017 via email

@arnsa
Copy link
Contributor

arnsa commented Mar 3, 2017

Uhm, downgrading react-native-tabs to 0.0.55 fixed the problem to me.

@dondragon2
Copy link

@arnsa how do I downgrade the react-native-tabs? I am using "react-navigation": "1.0.0-beta.5",

@mostr
Copy link

mostr commented Mar 7, 2017

Looks like it's already reported here satya164/react-native-tab-view#160

@martsie
Copy link

martsie commented Mar 9, 2017

Same issue for me, making it difficult to attach listeners to my components ...
Here's my tab navigator, each tab is another StackNavigator. If I put a breakpoint into component did mount of either of the screens then it fires twice despite only being shown to the user once.

const Parks = StackNavigator({
  Home: { screen: ParksScreen, },
  Landmarks: { screen: LandmarksScreen },
}, {
    headerMode: 'screen',
    initialRouteName: 'Home',
    navigationOptions: {
      ...stackNavOptions,
      tabBar: {
        label: 'Parks',
        icon: ({ tintColor, focused }) => (
          <Image
            source={focused ? require('./src/images/ios/alphabet-filled.png') : require('./src/images/ios/alphabet.png')}
            style={[styles.icon, { tintColor: tintColor }]}
          />
        ),
      },
    },
  });


const Closest = StackNavigator({
  Closest: { screen: ClosestScreen },
}, {
    headerMode: 'screen',
    navigationOptions: {
      ...stackNavOptions,
      tabBar: {
        label: 'Map',
        icon: ({ tintColor, focused }) => (
          <Image
            source={focused ? require('./src/images/ios/map-filled.png') : require('./src/images/ios/map.png')}
            style={[styles.icon, { tintColor: tintColor }]}
          />
        ),
      }
    },
  })
const TabNav = TabNavigator({
  Home: {
    screen: Closest,
  },
  Parks: {
    screen: Parks,
  },
}, {
    tabBarOptions: {
      initialRouteName: 'Home',
      activeTintColor: '#fff',
      inactiveTintColor: '#bbb',
      style: {
        backgroundColor: colors.blue,
      },
      titleStyle: {
        color: 'white',
      }
    },
  })

@martsie
Copy link

martsie commented Mar 9, 2017

Also stacktraces:

1st component mount

componentDidMount (ClosestScreen.js:62)
(anonymous) (ReactCompositeComponent.js:353)
measureLifeCyclePerf (ReactCompositeComponent.js:85)
(anonymous) (ReactCompositeComponent.js:352)
notifyAll (CallbackQueue.js:73)
close (ReactNativeReco…nsaction.js:36)
closeAll (Transaction.js:222)
perform (Transaction.js:163)
batchedMountComponentIntoNode (ReactNativeMount.js:77)
perform (Transaction.js:149)
batchedUpdates (ReactDefaultBat…Strategy.js:65)
batchedUpdates (ReactUpdates.js:111)
renderComponent (ReactNativeMount.js:141)
render (ReactNative.js:31)
renderApplication (renderApplication.js:33)
run (AppRegistry.js:76)
runApplication (AppRegistry.js:105)
__callFunction (MessageQueue.js:242)
(anonymous) (MessageQueue.js:108)
guard (MessageQueue.js:46)
callFunctionReturnFlushedQueue (MessageQueue.js:107)
(anonymous) (debuggerWorker.js:71)

Second component mount

componentDidMount (ClosestScreen.js:62)
(anonymous) (ReactCompositeComponent.js:353)
measureLifeCyclePerf (ReactCompositeComponent.js:85)
(anonymous) (ReactCompositeComponent.js:352)
notifyAll (CallbackQueue.js:73)
close (ReactNativeReco…nsaction.js:36)
closeAll (Transaction.js:222)
perform (Transaction.js:163)
perform (Transaction.js:149)
perform (ReactUpdates.js:95)
flushBatchedUpdates (ReactUpdates.js:199)
closeAll (Transaction.js:222)
perform (Transaction.js:163)
batchedUpdates (ReactDefaultBat…Strategy.js:65)
batchedUpdates (ReactUpdates.js:111)
_receiveRootNodeIDEvent (ReactNativeEventEmitter.js:126)
receiveEvent (ReactNativeEventEmitter.js:149)
__callFunction (MessageQueue.js:242)
(anonymous) (MessageQueue.js:108)
guard (MessageQueue.js:46)
callFunctionReturnFlushedQueue (MessageQueue.js:107)
(anonymous) (debuggerWorker.js:71)

In case that helps...

satya164 added a commit that referenced this issue Mar 10, 2017
@skevy skevy closed this as completed in ecef777 Mar 10, 2017
@duongtranpyco
Copy link

duongtranpyco commented Mar 16, 2017

This issue is still happened, please update to "react-native-tab-view": "^0.0.55"

lintonye added a commit to lintonye/react-navigation that referenced this issue Mar 25, 2017
* master:
  Docs: Update md links from coodoo's fork to react-community (react-navigation#750)
  Navigation Actions Doc (react-navigation#338)
  Update documentation regarding `DrawerNavigator` customisation (react-navigation#646)
  Fix flow in Navigation Playground (react-navigation#735)
  Adds documentation about forking and syncing repo (react-navigation#765)
  fix(docs): Fix incorrect style in TabNavigator sample (react-navigation#734)
  correction of a few documentation typo (react-navigation#563)
  Fix typo in docs for getComponentForRouteName (react-navigation#714)
  Drawer sidebar description (react-navigation#617)
  Remove 2nd return statement (react-navigation#661)
  Resolve gesture issues in CardStack
  Update dependencies
  Bump version number (react-navigation#650)
  Update react-native-tab-view. Fixes react-navigation#476 (react-navigation#641)
  Remove top margin from drawer view (react-navigation#642)
  Pass `transitionProps`, `prevTransitionProps` and `isModal` to custom `TransitionConfig` (react-navigation#565)
  Fix issue where initialRouteParams were not set (react-navigation#150)
@udfalkso
Copy link

udfalkso commented May 8, 2017

I'm currently running into this issue with 1.0.0-beta.9. My initial screen is a StackNavigator and the initial route of that stack is loaded twice, one on top of the other.

@NachtRitter
Copy link

I solved this problem with setting lazy: true for TabNavigator

@udfalkso
Copy link

udfalkso commented May 8, 2017

Thanks @NachtRitter but that isn't solving it for me.

@chrismcleod
Copy link

chrismcleod commented Jun 6, 2017

same as @udfalkso 1.0.0-beta.11

I am using redux and my reducer is exactly the same as the doc example. It seems this might be a misunderstanding of how to route to nested navigators. In the case below, it looks like it constructs and mounts a component for each route in the array of routes. I would think it would only instantiate the last one, maybe this is what lazy does?

class Screen1 extends React.Component {
  constructor(props) {
    super(props);
    console.log("constructed"); // called even though not the current route
  }

  componentDidMount() {
    console.log("mounted"); // called even though not the current route
  }
}

class Screen2 extends React.Component {
  constructor(props) {
    super(props);
    console.log("constructed"); // called
  }

  componentDidMount() {
    console.log("mounted"); // called
  }
}

const ChildNavigator = StackNavigator({
  Child1: {screen: Screen1},
  Child2: {screen: Screen2}
});

const ParentNavigator = StackNavigator({
  Parent: {screen: ChildNavigator}
});

initialState = {
  index: 1,
  routes: [{
    index: 0,
    routeName: "Parent",
    routes: [{
      index: 0,
      routeName: "Child1"
    }]
  },{
    index: 1,
    routeName: "Parent",
    routes: [{
      index: 0,
      routeName: "Child2"
    }]
  }]
}

I created the initialState by doing:

NavigationActions.navigate({
  routeName: "Parent",
  action: NavigationActions.navigate({ routeName: "Child2" })
})

Should the initialState instead be?:

initialState = {
  index: 0,
  routes: [{
    index: 1,
    routeName: "Parent",
    routes: [{
      index: 0,
      routeName: "Child1"
    },{
      index: 1,
      routeName: "Child2"
    }]
  }]
}

@udfalkso
Copy link

udfalkso commented Jun 6, 2017

Interesting @chrismcleod . I'm also using redux. This is how I'm generating my initial state.

var action = TabNav.router.getActionForPathAndParams("InitialTabView")
const initialState = TabNav.router.getStateForAction(action)

@chrismcleod
Copy link

chrismcleod commented Jun 6, 2017

@udfalkso
yea i created my first state in a similar way, but this initialState is actually coming from a rehydrate from redux-persist

@baldurpan
Copy link

+1

@neetocode
Copy link

+1
I have a TabNavigator nested a StackNavigator. The TabNavigator is mounted twice

@vagnerSl
Copy link

+1

1 similar comment
@hcyildirim
Copy link

+1

@aevpraid
Copy link

I have a StackNavigator nested a DrawerNavigator. The DrawerNavigator is mounted three time

@rubancar
Copy link

rubancar commented Sep 23, 2017

I was facing the same problem, I just found a simple solution, in my case MyApp is an StackNavigator which includes a TabNavigator and StackNavigator, the problem came up when I wanted to navigate from the Home screen in Main to Results screen in Purchase, so Results screen was double mounted, I solved this when I set Results as the name for my screen Purchase in MyApp, as you can see it's the same name of the initialRouteName in Purchase, so It appears that you have to use the same name of the initialRouteName on a StackNavigator as the name of the screen in another StackNavigator, I leave an example code that right now It's working for me.

const Purchase = StackNavigator({
    Results: { screen: Results },
    Seats: { screen: Seats }
}, {
    initialRouteName: 'Results',
    headerMode: 'none'
});

const Main = TabNavigator({
    Home: { screen: Home },
    Tickets: { screen: Tickets },
    Login: { screen: Auth }
}, {
    initialRouteName: 'Home'
});

export default MyApp = StackNavigator({
    Main: { screen: Main },
    Results: { screen: Purchase }
}, {
    initialRouteName: 'Main',
})

jsteiner added a commit to jsteiner/react-navigation that referenced this issue Sep 29, 2017
For some reason, when you open a screen in a modal StackNavigator, it
pushes twice.

I don't think this is the actual solution, but it does solve the problem
for me for now. I'll need more time to dig into this some more.

See this related issue for more: react-navigation#476 (comment)
@pencilcheck
Copy link

pencilcheck commented Oct 5, 2017

Having the same issue for stacknavigator that loads the first screen twice, and you can see that the same screen get flashed twice. I don't know how to solve this, even the most simpliest example from the playground also produce the same results here somehow.

Using

react-navigation@^1.0.0-beta.13:
  version "1.0.0-beta.13"
  resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-1.0.0-beta.13.tgz#77521f7080e5755906a3483a28baedbbc66f763c"
  dependencies:
    babel-plugin-transform-define "^1.3.0"
    clamp "^1.0.1"
    hoist-non-react-statics "^2.2.0"
    path-to-regexp "^1.7.0"
    prop-types "^15.5.10"
    react-native-drawer-layout-polyfill "^1.3.2"
    react-native-tab-view "^0.0.69"

Downgrading to 1.0.0-beta.9 fixed the issue...

@NunoCardoso
Copy link

+1

@lucidtheory
Copy link

lucidtheory commented Oct 20, 2017

Solved this by naming everything down the tree by the same name as per @rubancar 's post:


  const MainNavigator = TabNavigator({
        welcome: {screen: WelcomeScreen},
        auth: {
          screen: StackNavigator({
            login: { screen: LoginScreen },
            register: { screen: RegisterScreen },
            forgotPassword: {screen: ForgotPasswordScreen},
            eula: {screen: EULAScreen},
          })
        },
        contacts:{
          screen: TabNavigator({
            contacts:{
              navigationOptions:{
                tabBarVisible: false
              },
              screen: TabNavigator({
                contacts: {
                  screen: StackNavigator({
                    //-------this is the first screen to render --------
                    contacts: { screen: ContactsScreen },
                    viewProfile: {
                      screen: ViewProfileScreen,
                      navigationOptions: ({ navigation }) => ({
                        tabBarVisible: false,
                        headerBackTitle: null
                      })
                    },
......more code

for me my first main screen is my contacts screen so I just renamed every branch down the tree contacts. Not the best thing as far as naming principles is concerned but it works and its a simple fix.

jsteiner added a commit to jsteiner/react-navigation that referenced this issue Nov 5, 2017
For some reason, when you open a screen in a modal StackNavigator, it
pushes twice.

I don't think this is the actual solution, but it does solve the problem
for me for now. I'll need more time to dig into this some more.

See this related issue for more: react-navigation#476 (comment)
@Kottidev
Copy link

This issue still exist with last version 1.0.0-beta.19 when using Redux and TabNavigator.

componentWillMount is called twice

@grabbou

@ruinnel
Copy link

ruinnel commented Nov 24, 2017

still existing version 1.0.0-beta.21

in my case.
TabNavigator has 4 tab and each tab has StackNavigator..

I solved this problem using custom router.

in router.getStateForAction receive two action..

  1. { type: 'Navigation/INIT' }
  2. Navigation/Navigate for move to your initialRouteName in TabNavigator.

skip second action like this.

const defaultGetStateForAction = Nav.router.getStateForAction;

Nav.router.getStateForAction = (action, state) => {
  if (action && action.type === 'Navigation/NAVIGATE'
  && action.routeName === 'reserve'
  && action.action && action.action.routeName === 'main') {
    const index = _.get(state, 'routes.[0].index');
    const routeName = _.get(state, 'routes.[0].routes[0].routeName');
    if (index === 0 && routeName === 'main') {
      return state;
    }
  }

  return defaultGetStateForAction(action, state);
};

please change

  • Nav to your StackNavigator
  • routeName === 'main' to routeName === 'StackRouter's initialRouteName'

I am sorry that English is awkward.....

@EthanChouTW
Copy link

@luisfuertes 's fixs works for me, thanks

change from

const firstAction = AppNavigator.router.getActionForPathAndParams('Home');
const initialNavState = AppNavigator.router.getStateForAction(firstAction)

to

 const initialNavState = AppNavigator.router.getStateForAction({})

and
add initialRouteName in navigatorConfig

could prevent multiple mount calls for me

@mlazari
Copy link

mlazari commented Dec 27, 2017

@satya164 Here is a repro: https://snack.expo.io/BJLIk4-Qz

@zygama
Copy link

zygama commented Dec 30, 2017

I have the same problem in beta-22 ...

TabNavigator -> StackNavigator -> StackNavigator (mount twice)

@thalesfp
Copy link

thalesfp commented Jan 7, 2018

@rubancar solution works for me.

mlazari pushed a commit to mlazari/react-navigation that referenced this issue Jan 10, 2018
Screen loads twice when using TabNavigator
react-navigation#476
@mlazari
Copy link

mlazari commented Jan 10, 2018

Repro code: https://snack.expo.io/BJLIk4-Qz

Navigation structure:

MyTabNavigator
--MyStackNavigator
----MyScreen1

Problem: MyScreen1 loads twice

Possible cause:
MyScreen1 is loading first time when MyTabNavigator's router is sending Navigation/INIT to MyStackNavigator router's getStateForAction here:
TabRouter -> StackRouter
Second time it's loading when MyTabNavigator's router is sending Navigation/NAVIGATE to MyStackNavigator router's getStateForAction here:
TabRouter -> StackRouter

Possible solutions:
const initialAction = MyTabNavigator.router.getActionForPathAndParams('MyStackNavigator');
The value of initialAction is:

{
  type: "Navigation/NAVIGATE",
  routeName: "MyStackNavigator",
  action: {
    type: "Navigation/NAVIGATE",
    routeName: "MyScreen1"
  }
}

const initialState = MyTabNavigator.router.getStateForAction(initialAction);
The value of initialState is:

{
  index: 0,
  routes: [
    {
      index: 1,
      key: "MyStackNavigator",
      routeName: "MyStackNavigator",
      routes: [
        {
          key: "Init-id-1515587457094-0",
          routeName: "MyScreen1"
        },
        {
          key: "id-1515587457094-1",
          params: undefined,
          routeName: "MyScreen1"
        }
      ]
    }
  ]
}

I think the inner action (Navigate to MyScreen1) is adding the screen for the second time in stack. initialAction should be probably just:

{
  type: "Navigation/NAVIGATE",
  routeName: "MyStackNavigator"
}

because I'm asking MyTabNavigator's router which action do I need to go to MyStackNavigator, not to MyScreen1.
The inner action is added here: TabRouter -> StackRouter
It should probably not add the subaction when the remaining part of the path is empty. I've made a commit here which does that: mlazari@29f0c1d Maybe someone from contributors can review it?

Other solution for given code would be to just use NavigationActions.navigate instead of MyTabNavigator.router.getActionForPathAndParams:
const initialAction = NavigationActions.navigate({routeName: 'MyStackNavigator'});

Or just const initialAction = {}; as someone already suggested.

@Donhv
Copy link

Donhv commented Jan 23, 2018

who can help me fix this issue?

@udfalkso
Copy link

udfalkso commented Feb 5, 2018

@mlazari is def. right. Using a sort of "empty" action for your initial state can stop this issue from happening. This seems like the cleanest way to do it.

import { NavigationActions } from "react-navigation"

let initialState = MainTabs.router.getStateForAction(NavigationActions.init())

Should the redux docs be updated to reflect this?

@SKempin
Copy link

SKempin commented Feb 22, 2018

Just upgraded to 1.1.2 and am getting this with the Stack and Tabs navigators. Should this be fixed by now?

@danZheng1993
Copy link

I have upgraded the react native to 1.2.1 and the issue was fixed.
It works like magic now.
Fantastic work by the team.

@SKempin
Copy link

SKempin commented Feb 28, 2018

1.2.1 has solved this issue for me too.

@brentvatne
Copy link
Member

yay thanks

@brentvatne
Copy link
Member

given that this is resolved i will lock the issue. if you run into any other bugs please create a new issue. thanks!

@react-navigation react-navigation locked as resolved and limited conversation to collaborators Mar 6, 2018
sourcecode911 pushed a commit to sourcecode911/react-navigation that referenced this issue Mar 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests