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

TabNavigator does not pass params to children when using NAVIGATE action within RESET action #2073

Closed
jordanmkoncz opened this issue Jul 6, 2017 · 11 comments
Labels

Comments

@jordanmkoncz
Copy link

Current Behavior

Suppose you have the following navigation structure:

  • MainStackNavigator
    • TabNavigatorA
      • ScreenA
      • ScreenB
    • TabNavigatorB

If you dispatch a NAVIGATE action, for example:

{
  type: 'Navigation/NAVIGATE',
  routeName: 'TabNavigatorA',
  params: {
    contactId: '50',
  }
}

The result of this action is that the params from the NAVIGATE action will be passed down to all children of TabNavigatorA, i.e. ScreenA and ScreenB will receive the params from the NAVIGATE action via navigation.state.params. This is working as expected.

However, if you dispatch an equivalent RESET action, for example:

{
  type: 'Navigation/RESET',
  index: 0,
  actions: [
    {
      type: 'Navigation/NAVIGATE',
      routeName: 'TabNavigatorA',
      params: {
        contactId: '50'
      }
    }
  ]
}

The result of this action is that the params from the NAVIGATE action will not be passed down to any children of TabNavigatorA, i.e. navigation.state.params will be undefined in ScreenA and ScreenB.

Expected Behavior

The behaviour of a TabNavigator should be the same in both of the above examples since the NAVIGATE actions are identical, i.e. the params from the NAVIGATE action should be passed down to all children in both of these cases.

Notes

I believe this is the same problem as @TGNC describes here: #143 (comment). His workaround of dispatching an INIT action within the RESET action (instead of a NAVIGATE action) does seem to work for me, but I believe the expected behaviour I've described above is how it should work and you shouldn't need to use @TGNC's workaround to fix this issue.

Your Environment

software version
react-navigation 1.0.0-beta.11
react-native 0.45.1
@alexn777
Copy link

I have the same issue with react-native v0.48.4 and react-navigation v1.0.0-beta.12.

@adkl
Copy link

adkl commented Sep 25, 2017

@alexn777 You can call the init() function instead of navigate(). That worked for me.

    onContinueAs = () => {
        const resetAction = NavigationActions.reset({
            index: 0,
            actions: [NavigationActions.init({
                        routeName: 'EventsNavigator',
                        params: {
                          onLogout: this.onLogout,
                          user: this.state.user
                        }
                      })]
        })
        this.props.navigation.dispatch(resetAction)
    }

@alexn777
Copy link

@adkl Yes, it works. Thank you!

@jordanmkoncz
Copy link
Author

@adkl @alexn777 yep I mentioned in the "Notes" section of this issue that dispatching an INIT action is a workaround that seems to resolve the issue, so I'd definitely suggest doing that in the meantime until this bug is fixed. 😃

@adkl
Copy link

adkl commented Oct 4, 2017

Sorry I didn't see :)

@RnMss
Copy link

RnMss commented Dec 31, 2017

I'm now using '1.0.0-beta22' and the bug still exists.

But @adkl 's workaround doesn't work anymore.
And I got

Invariant Violation: Cannot get config because the route does not have a routeName.

@RnMss
Copy link

RnMss commented Dec 31, 2017

Well...

now I have another workaround.

        const resetAction = NavigationActions.reset({
            index: 0,
            actions: [
                 {
                        type: 'Navigation/INIT',
                        routeName: 'someTabNavigator',
                        params: {
                           arg1: 1,
                           arg2: 2,
                        }
                  }
             ]
        })
        this.props.navigation.dispatch(resetAction)

@khumphrey-sb
Copy link

I'm also having this issue and the typings aren't allowing me to even use the workaround without overriding them with my own.

@khumphrey-sb
Copy link

khumphrey-sb commented Feb 1, 2018

Seems the reason your workaround works is here: https://github.com/react-navigation/react-navigation/blob/master/src/routers/TabRouter.js#L68

if (action.type === NavigationActions.INIT) {
        // Merge any params from the action into all the child routes
        const { params } = action;
        if (params) {
          state.routes = state.routes.map(route => ({
            ...route,
            params: {
              ...route.params,
              ...params,
              ...(route.routeName === initialRouteName
                ? initialRouteParams
                : null),
            },
          }));
        }
      }

The NAVIGATE action isn't propagating the params to child routes. Changing this to:

if (action.type === NavigationActions.INIT || action.type === NavigationActions.NAVIGATE) {

fixes the issue for me, but I can't speak to the ramifications of this change.

@kanteankit
Copy link

kanteankit commented Mar 7, 2018

@jordanmkoncz Hi I am still facing this issue in v1.4.0. Please tell me what is wrong. I am using the workaround that you have suggested,but its not working. I have the following setup.


const NewsFeedStack = StackNavigator({
	NewsFeed:{
		screen: NewsFeed
	},

})
export const HomeScreenTabNavigator = TabNavigator(
	{
		NewsFeed:{
			screen:NewsFeedStack,
		},
		Search:{
			screen: Search,
		},
		Notification:{
			screen: Notification,
		},
		Community:{
			screen: Community
		}
	},
);
export const RootNavigator = StackNavigator(
	{
		Splash:{
			screen: SplashScreen,
			navigationOptions:{
				header:null
			}
		},
		Home:{
			screen:HomeScreenTabNavigator,
		},
		
	},{
		initialRouteName:'Splash'
	}

Inside my SplashScreen I am sending user as a param using the following code:

let action = NavigationActions.init({ 
            routeName: 'Home',
	  params:{
		 loginMode:'email',
		  user:user 				
           } 
 });

let navigateAction = NavigationActions.reset({
	index:0,
       actions: [
	    action
       ]
})

this.props.navigation.dispatch(navigateAction)

Inside my NewsFeed screen I am trying to get the user param like this:

componentDidMount() {	
      // Throws error here.Both user and loginMode are undefined
       const {loginMode,user} = this.props.navigation.state.params;
}

@brentvatne
Copy link
Member

moving discussion over to react-navigation/rfcs#43 because this is not a bug (unless i'm totally misunderstanding, in which case please explain it to me on that rfc issue), but rather the behavior is not well explained and also not obvious

@react-navigation react-navigation locked and limited conversation to collaborators May 7, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

9 participants