1

when I tried to refactor the mobile app of 'Notes' from ‘JavaScript Everywhere’ book, a problem

The structure is like this:

RootNavigator(Stack.Navigator)
---AuthLoading(Screen)
---Auth(Stack.Navigator)
   --SignIn(Screen)
   --SignUp(Screen)
---App(Tab.Navigator)
   --FeedStack(Stack.Navigator)
     -FeedScreen(Screen)
     -NoteScreen(Screen)
   --MyNotesStack(Stack.Navigator)
     -MyNotesScreen(Screen)
     -NoteScreen(Screen)
   --FavoritesStack(Stack.Navigator)
     -FavoritesScreen(Screen)
     -NoteScreen(Screen)
   --SettingsStack(Stack.Navigator)

When a user login, the default tab is ‘Feed’ which goes to ‘FeedStack’, and FeedScreen list all the notes created by all the users, click one item of the notes, it goes to a NoteScreen, display the details of that ‘Note’, everything goes well.

When the user choose ‘MyNotes’ tab which goes to ‘MyNoteStack’, it list the notes created by the current user, click one of the ‘note’ item, it goes to NoteScreen, display the details of that ‘note’. However, now, the default focus of the Tab.Navigator is ‘Feed’, and when I click back button in the NoteScreen, it goes back to ‘FeedStack’ which displays all the notes. It is weird!

I can’t understand why I go to the NoteScreen from ‘MyNotes’, but back button leads it to ‘Feed’, how to fix this problem?

And the code is as follows.

In index.js (RootNavigator)

const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
const AuthStack = createNativeStackNavigator();
const feedStack = createNativeStackNavigator();
const myNotesStack = createNativeStackNavigator();
const favoritesStack = createNativeStackNavigator();
const settingsStack = createNativeStackNavigator();

function FeedStack () {
  return (
    <feedStack.Navigator
      screenOptions={
        {headerShown:false}
      } 
    >
      <feedStack.Screen name="FeedScreen" component={FeedScreen} />
      <feedStack.Screen name="NoteScreen" component={NoteScreen} options={{headerShown:true}}/>
    </feedStack.Navigator>
  );
}

function MyNotesStack () {
  return (
    <myNotesStack.Navigator 
      screenOptions={
        {headerShown:false}
      } 
    >
      <myNotesStack.Screen name="MyNotesScreen" component={MyNotesScreen} />
      <myNotesStack.Screen name="Note" component={NoteScreen} options={{headerShown:true}} />
    </myNotesStack.Navigator>
  );
}

function FavoritesStack () {
  return (
    <favoritesStack.Navigator 
      screenOptions={
        {headerShown:false}
      } 
    >
      <favoritesStack.Screen name="FavoritesScreen" component={FavoritesScreen} />
      <favoritesStack.Screen name="Note" component={NoteScreen} options={{headerShown:true}}/>
    </favoritesStack.Navigator>
  );
}

function SettingsStack () {
  return (
    <settingsStack.Navigator 
      screenOptions={
        {headerShown:false}
      } 
    >
      <settingsStack.Screen name="SettingsScreen" component={SettingsScreen} />
    </settingsStack.Navigator>
  );
}

const TabNavigator = () => {
  return (
    <Tab.Navigator
      initialRouteName="MyNotes"
      activeColor='#f0f'
      inactiveColor='#555'
      barStyle={{
        backgroundColor:'#999'
      }}
      screenOptions={({route}) => ({
        headerShown: false,
        tabBarIcon:({focused, size, color}) => {
        let iconName;
        if( route.name === 'FeedStack') {
          iconName = 'home';
        } else if (route.name === 'MyNotesStack') { 
          iconName = 'bed';
        } else if (route.name === 'FavoritesStack') {
          iconName = 'star'
        } else {
          iconName = 'spa'
        }
        color = focused ? '#f0f' : "#555";
        size = focused ? 24 : 20;
        return <FontAwesome5 name={iconName} size={size} color={color}/>;
     },
     })}
    >
      <Tab.Screen name='FeedStack' component={FeedStack} options={{headerShown: false}} />
      <Tab.Screen name='MyNotesStack' component={MyNotesStack} options={{headerShown: false}} />
      <Tab.Screen name='FavoritesStack' component={FavoritesStack} options={{headerShown: false}}/>
      <Tab.Screen name='SettingsStack' component={SettingsStack} options={{headerShown: false}} />
    </Tab.Navigator>
  );
};

const Auth= () => {
  return (
    <AuthStack.Navigator
      screenOptions={{headerShown:false}}
    >
      <AuthStack.Screen name='signIn' component={SignIn}></AuthStack.Screen>
    </AuthStack.Navigator>
  );
};

const RootNavigator = () => {
  return ( 
    <Stack.Navigator initialRouteName='AuthLoading'>
      <Stack.Screen name='AuthLoading' 
        component={AuthLoading} 
        options={{title:'AuthLoading'}}
      >
      </Stack.Screen>
      <Stack.Screen name='Auth' 
        component={Auth} 
        options={{
          title: 'Auth',
          headerStyle: {
          backgroundColor: '#f4511e',
        },
        headerBackVisible: false,
        headerTintColor: '#fff',
        headerTitleStyle: {
          fontWeight: 'bold',
        },
        }}
      >
      </Stack.Screen>
      <Stack.Screen name='App' 
        component={TabNavigator} 
        options={{
          title: 'App',
          headerStyle: { backgroundColor: '#f4511e'},
          headerBackVisible:false,
          headerTintColor: '#fff',
          headerTitleStyle: {fontWeight: 'bold'},
        }}
      > 
      </Stack.Screen>
    </Stack.Navigator>
  );
};
export default RootNavigator;

In FeedScreen.js:

const FeedScreen = () => {
  const { data, loading, error } = useQuery(GET_NOTES);
  // if the data is loading, our app will display a loading indicator
  if(loading)
    return <Loading />;
  if(error)
    return <Text>Error loading notes.</Text>;

  // if the query is successful and there are notes, return the feed of notes
  return (
    <NoteFeed notes={data.notes} />
  );
};

In MyNotesScreen.js

const MyNotesScreen = () => {
  const { data, loading, error } = useQuery(GET_MY_NOTES);
  // if the data is loading, our app will display a loading indicator
  if(loading)
    return <Loading />;
  if(error)
    return <Text>Error loading MyNotes.</Text>;

  // if the query is successful and there are notes, return the feed of notes
  // else if the query is successful and there aren't notes, display a message
  if(data.me.notes.length !== 0) {
    return <NoteFeed notes={data.me.notes} />;
  } else {
    return <Text>No notes yet</Text>;
  }
  // If I don't use <NoteFeed> here, for example, show a button then go to <NoteScreen> it is ok.
  // return (
  // <View style={styles.container}>
  // <Text>My Notes Screen</Text>
  // use self-defined button
  // <JereButton 
  // onPress={() => navigation.navigate('Note',{id:'63b94da5ccf7f90023169c3d'})} 
  // title="Go to a note" 
  // color={"#882"}
  // />
  // </View>
  // );
};

In NoteFeed.js

const NoteFeed = props => { 
  // only screen components receive navigation prop automatically!
  // if you wish to access the navigation prop in any of your components, you may use the useNavigation hook.
  const navigation = useNavigation();

  return (
    <View style={styles.container}>
      <FlatList 
        data={props.notes}
        keyExtractor = {({id}) => id.toString()}
        renderItem = {({item}) => ( 
          <Pressable style={styles.feedview} 
            onPress={() => navigation.navigate('NoteScreen',{id: item.id})}
          >
            <Text style={styles.text}>{item.content}</Text>
          </Pressable>
        )}
       />
     </View>
  ); 
};

In NoteScreen.js

const NoteScreen = ({navigation, route}) => {
  const {id} = route.params;

  const { data, loading, error } = useQuery(GET_NOTE, {variables:{id}});
  // if the data is loading, our app will display a loading indicator
  if(loading)
    return <Loading />;
  if(error)
    return <Text>Error Note not found.</Text>;

  return (
    <Note note={data.note} />
  );
};

Thank you for your help.

I tried to replace useNavigation() to props solution, the issue is the same. Then I tried to do not use in 'MyNotes' to show the ‘note’, it is OK, but it doesn’t comply with the design.

JeremyQin
  • 31
  • 4
  • 1
    Are you sure the route for NoteScreen has different names in FeedStack and MyNotesStack and the proper route name depending on the stack is used to navigate to NoteScreen? – user18309290 Jan 21 '23 at 06:10
  • Thank you. You find the key! Inside function MyNotesStack () {}, Should be – JeremyQin Jan 21 '23 at 07:12
  • I haven’t understood yet. when I made wrong (in MyNotesStack, name =“Note”), when navigation.navigate(“NoteScreen”),it can’t find a screen named “NoteScreen”,so it looked for the screen in its ‘brother’ stack “Feed Stack” and render with new data?Is there any way to “log” related “screen history“ or help me find understand it? – JeremyQin Jan 22 '23 at 06:15

0 Answers0