React-native-router-flux: Actions error and navigationState.children conflicts with another child!

Created on 5 Jun 2016  路  18Comments  路  Source: aksonov/react-native-router-flux

Version

  • react-native-router-flux v3.26.16
  • react-native v0.25.1

    Expected behaviour

Actions.[SCENE_NAME] work correctly.

Actual behaviour

Actions.[SCENE_NAME]聽jump to another scene

Steps to reproduce

  1. scene config

    reducerCreate(params) {
        const defaultReducer = Reducer(params);
        return (state, action)=>{
           return defaultReducer(state, action);
       }
    }
    
    
    <Router
       createReducer={reducerCreate()}
       >
     <Scene key="modal" component={Modal}>
       <Scene key="root" hideNavBar={false} >
         <Scene key="product" component={Product} title="Item" />
         <Scene key="newsItem" component={NewsItem} title="News Item" />
         <Scene key="tabbar" tabs={true} initial={true} >
           <Scene key="main" title="Main" component={ProductList} />
           <Scene key="news" title="News" component={News} />
           <Scene key="order" title="Order" component={Order} />
         </Scene>
       </Scene>
     </Scene>
    </Router>
    

2.

  • from the main page, is a product listview, click on the item will jump to product scene
  • on the product page, click a button jump to order scene by Actions.order( {title: 'order'} ); this stey can by done in the componentDidMount() { Actions.order( {title: 'order'} ); }
  • now the current page is the order scene.
    if you click on the tabbar News, then click on the News listview, normally it will jump to the newsItem scene, but it jump to product scene.
    if you click on the tabbar Main, then click on the ProductList listview, normally it will jump to the product scene, but it shows the red screen with the message: navigationState.clilcren[2].key"scene_1_product" conflicts with another child!

Most helpful comment

@AndrewHenderson

Try adding:

type={ActionConst.RESET}

as a prop to your 'Login' scene. You may also have to add the prop to the parent scene, if that's what you navigate to. For example, when I logout I navigate to Actions.auth(), which starts at my login scene. So I had to add type={ActionConst.RESET} to the Auth scene as well.

Example:

            <Scene key="auth" barButtonIconStyle={{ tintColor:'black' }} type={ActionConst.RESET}  >
              <Scene key="login" 
                                    component={LoginForm} 
                                    title="Login" 
                                    type={ActionConst.RESET} />
              <Scene key="register" 
                                    component={RegisterForm} 
                                    title="Register" 
                                    onBack={() => this.onBackToLogin() }  />
            </Scene>

This worked for me, good luck!

All 18 comments

i think you're doing nesting wrong. check out this code snippet from the Example:

                  <Scene key="tabbar" component={NavigationDrawer}>
                        <Scene key="main" tabs={true} >
                            <Scene key="tab1"  title="Tab #1" icon={TabIcon} navigationBarStyle={{backgroundColor:"red"}} titleStyle={{color:"white"}}>
                                <Scene key="tab1_1" component={TabView} title="Tab #1_1" onRight={()=>alert("Right button")} rightTitle="Right" />
                                <Scene key="tab1_2" component={TabView} title="Tab #1_2" titleStyle={{color:"black"}}/>
                            </Scene>
                            <Scene key="tab2" initial={true} title="Tab #2" icon={TabIcon}>
                                <Scene key="tab2_1" component={TabView} title="Tab #2_1" renderRightButton={()=><Right/>} />
                                <Scene key="tab2_2" component={TabView} title="Tab #2_2" onLeft={()=>alert("Left button!")} leftTitle="Left" duration={1} panHandlers={null}/>
                            </Scene>
                            <Scene key="tab3" component={TabView} title="Tab #3" hideTabBar={true} icon={TabIcon}/>
                            <Scene key="tab4" component={TabView} title="Tab #4" hideNavBar={true} icon={TabIcon}/>
                            <Scene key="tab5" component={TabView} title="Tab #5" hideTabBar={true} hideNavBar={true} icon={TabIcon}/>
                        </Scene>
                    </Scene>

@xrjxs @281330 is right, also you could use 'clone' attribute to push 'cloned' scene from anywhere.

I'm running into this same issue using the following code:

export default Actions.create(
  <Scene key="root">
    <Scene key="login" component={Login} initial hideBackImage />
    <Scene key="main"
           tabs
           tabBarStyle={styles.tabBarStyle}
           tabBarSelectedItemStyle={styles.tabBarSelectedItemStyle}
    >
      <Scene
        initial
        key="tab1"
        title="Events"
        component={EventsFeed}
        icon={TabIcon}
        iconName="home"
        hideBackImage
      />
      <Scene
        key="tab2"
        title="Create Event"
        component={EventForm}
        icon={TabIcon}
        iconName="event"
        hideBackImage
      />
      <Scene
        key="tab3"
        title="Profile"
        component={Profile}
        icon={TabIcon}
        iconName="person"
        hideBackImage
      />
    </Scene>
  </Scene>
);

Once the user has authenticated, I direct him to the main scene. Within main is a tab, profile, which has a logout button.

When the user clicks that I direct him to the login scene. When the user logs back in and goes to profile tab and logs out again, I get the following error screen:

screen shot 2016-11-26 at 1 47 57 pm

@AndrewHenderson -I'm having the same exact problem. Did you find a solution?

@Ross-Landry No. It's still happening for me. I've put resolving this issue on the back burner for now.

The message makes me think the router is trying to navigate from the same page "login" to itself.

@AndrewHenderson

Try adding:

type={ActionConst.RESET}

as a prop to your 'Login' scene. You may also have to add the prop to the parent scene, if that's what you navigate to. For example, when I logout I navigate to Actions.auth(), which starts at my login scene. So I had to add type={ActionConst.RESET} to the Auth scene as well.

Example:

            <Scene key="auth" barButtonIconStyle={{ tintColor:'black' }} type={ActionConst.RESET}  >
              <Scene key="login" 
                                    component={LoginForm} 
                                    title="Login" 
                                    type={ActionConst.RESET} />
              <Scene key="register" 
                                    component={RegisterForm} 
                                    title="Register" 
                                    onBack={() => this.onBackToLogin() }  />
            </Scene>

This worked for me, good luck!

@Ross-Landry That worked! Thanks for posting!

@Ross-Landry @AndrewHenderson
I understand this works for the log-out case, in which you indeed would want to reset the navigation stack. But I have the following scenario:

  1. user is on scene A and clicks a browse button which redirects to scene B
  2. user navigates further, from B to C, from C to D (amount of browsing can differ)
  3. at scene C, user does an action and now I want him to be redirected to scene A, currently scene A has type PUSH because you arrive, in the beginning at scene A via scene Z and you have to be able to use the back-button.... so I try to Actions.sceneA(); but this throws the navigationState.children issue, because it is trying to add the scene again to the stack, is there a way for me to redirect to scene A without using REPLACE for example? Any suggestion?

Hi,

Not sure what unmountScenes does, so far seems this only sets index back to 0 but doesn't actually reset history stack which is why I have the same problem.

Example:
<Scene key="main" tabs unmountScenes hideTabBar>

<Scene key="auth">
    <Scene key="intro">
    <Scene key="login" type="push">
</Scene>
<Scene key="app" tabs hideTabBar={false}>
    <Scene key="dashboard">
     <Scene key="menu">
</Scene>

</Scene>

Steps to reproduce:

  1. auth is the initial tab & intro is the initial scene
  2. push from intro to login
  3. jump from auth to app
  4. jump from app to auth (on logout)
  5. now state for auth tab is broken because index (unmountScenes) is set to 0, but auth still has 2 children and child with index 1 is login and this is where push gets conflict

By setting login type to ActionConst.PUSH_OR_POP seems to work just fine, BUT...

Can someone confirm pushOrPop is the correct option here or my scene nesting is wrong?

@JeroenNelen

Does Scene A always go back to Scene Z when you click the 'back' button on the nav bar? If that's the case then I could suggest a workaround.

@Ross-Landry that's a scenario we can consider yes, to always have sceneA's back button to redirect to sceneZ.
RESET to sceneA is not an option, because then we can not go back to sceneZ from sceneA as the stack was cleared.

@JeroenNelen you can define the scene that the back button navigates to using the 'onBack' prop of the Scene component.

So for sceneA set:
onBack={()=> Actions.sceneZ() }

Once you've done this then you can make sceneA type RESET.

I've run into this issue again.

Version

Tell us which versions you are using:

  • react-native-router-flux v3.36.0
  • react-native v0.37.0

Expected behaviour

I'm hoping to be able to open a vertical modal from a tab. The behavior I'm seeking to recreate is that seen in Instagram when a user presses the camera icon.

Instagram

instagram

When a user clicks the icon camera tab button, the following full screen view slides up:

Me

sceneconflict

Code

export default Actions.create(
  <Scene key="modal" component={Modal}>
    <Scene key="root">
      <Scene key="login"
             component={Login}
             initial={true}
             hideNavBar
             type={ActionConst.RESET}
      />
      <Scene key="main"
             tabs
             tabBarStyle={styles.tabBarStyle}
             tabBarSelectedItemStyle={styles.tabBarSelectedItemStyle}
      >
        <Scene
          initial={true}
          key="events"
          icon={TabIcon}
          iconName="md-home"
        >
          <Scene initial={true}
                 key="events_list"
                 renderBackButton={()=>(null)}
                 component={EventsFeed}
                 title="Main"
                 rightButtonIcon="ios-add"
                 onRight={() => { Actions.event_form() }}
          />
        </Scene>
        <Scene key="publish" icon={TabIcon} onPress={() => { Actions.event_form() }} iconName="md-pin"></Scene>
        <Scene
          key="my_profile"
          icon={TabIcon}
          iconName="md-person"
        >
          <Scene key="my_profile_initial" initial={true} renderBackButton={()=>(null)} component={Profile} getTitle={getProfileTitle} rightButtonIcon="ios-settings" onRight={() => { Actions.my_profile_settings() }} />
        </Scene>
      </Scene>
      <Scene
        key="event_form"
        direction="vertical"
      >
        <Scene
          key="event_form_initial"
          title="New Event"
          component={EventForm}
          leftTitle="Cancel"
          onLeft={() => { Actions.events() }}
          rightTitle="Add"
          onRight={() => { Actions.refresh({ triggerSave: true }) }}
        />
      </Scene>
    </Scene>
  </Scene>
);

Resolved using Actions.pop on the onLeft of event_form_initial.

Use NavigationActions.pop() before push fix it for me, example:

   NavigationActions.pop();
   setTimeout(()=> NavigationActions[to](options));

Isn't there a cleaner solution? I have to do this in several places in order to avoid the crashes, it's insane!

Unfortunately ExperimentalNavigation API is very buggy and already deprecated by React Native team.
I'm working now on v4 version now that uses new http://reactnavigation.org and actively looking for contributors:
#1595

@aksonov it is brilliant news! Good luck!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wootwoot1234 picture wootwoot1234  路  3Comments

booboothefool picture booboothefool  路  3Comments

VictorK1902 picture VictorK1902  路  3Comments

sarovin picture sarovin  路  3Comments

YouYII picture YouYII  路  3Comments