Search code examples
javascriptreactjsreact-nativescreennavigator

React Native: How to change/navigate the Screen as a Childcomponent?


Every little help is appreciated very much!

I got an Avatar as a Navigator, which should allow me to navigate through some screens! Some other Screens should be reached only by the my home screen. But when I press on the Button in the Avatar, nothing happens. I don't understand how and why, but I believe I made a mistake in the stackNavigator somewhere? Just to avoid any misunderstanding, the code below is shortened to avoid filling the page with unnecessary information, so it doesn't reflect 1:1 what you see in the screenshots.

Home Screen which should change

Avatar Screen through which I should be able to change the Home Screen

The goal is to be able to change which Screen is displayed in the <AppContainer/> through the <Avatar/> component below.

I tried with a onPress function inside the Avatar.js to call this.props.navigation.navigate("Agenda") but the screen didn't change. At least I got rid of the errors thanks to passing the navigation prop. I believe I made kind of a scrub mistake since i'm not experienced with react native, I hope some of the more experienced users can help me with that :) furthermore I don't think the screen itself is important to solve this, it's just a class component with panresponder and animated view.

import React from "react";
import { StyleSheet, View, StatusBar } from "react-native";
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";

import Avatar from "../coreComponents/Avatar";

import ScHome from "../screens/ScHome";
import ScNewMedi from "../screens/ScNewMedi";
import ScCalendar from "./ScAgenda";

const AppStack = createStackNavigator(
  {
    Home: {
      screen: ScHome,
    },
    Medis: {
      screen: ScNewMedi,
    },
    Agenda: {
      screen: ScCalendar,
    },
  },
  {
    headerMode: "screen",
    initialRouteName: "Home",
    backBehavior: "order",
  }
);

const AppContainer = createAppContainer(AppStack);

export default class ScDefault extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <StatusBar
          barStyle="light-content"
          backgroundColor="transparent"
          translucent
        />
        <AppContainer />
        <Avatar navigation={this.props.navigation} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

Solution

  • The problem is you are trying to access navigation outside the Appcontainer where the navigation is not available.

    Easy fix : Moving the Avatar component inside one of your main screens(ScHome,ScNewMedi,ScCalendar) then you will have access to navigation and everything will work as expected.

    Workaround : Let say the requirement is to have the Avatar outside the AppContainer then you have to use something like a navigation service.

    The code would be as below

    let _navigator;
    
    const setTopLevelNavigator=(navigatorRef) =>{
      _navigator = navigatorRef;
    }
    
    const  navigate=(routeName, params) =>{
      _navigator.dispatch(
        NavigationActions.navigate({
          routeName,
          params,
        })
      );
    }
    
    //Change your app.js
     return <View style={{flex:1}}>
          <AppContainer
        ref={navigatorRef => {
          setTopLevelNavigator(navigatorRef);
        }}
      />
     <Avatar navigate={navigate} /></View>;
    
       //Inside the Avatar onPress you can can do this
       onPress={()=>this.props.navigate("Home")}
    

    You can refer the docs for more details