NOTE
This documentation is the same for both the customer and clerk applications.
# Overview
React Navigation 5 offers a completely new API based on components rather than JSON-serializable objects.
# Relevant files
AppNavigator.js
navigation/stack_navigators
DrawerContent.js
# Existing stacks
Currently, the following stacks exist:
AppStack(AppNavigator.js): Screens accessible within the app, as provided by drawer tabsAuthStack(stack_navigators/AuthStack.js): Deals with authorization screens like sign up and login
Customer app only
NewsStack(stack_navigators/NewsStack.js): Currently unusedResourcesStack(stack_navigators/ResourcesStack.js): Points to the resources screen, accessible via the drawerStoresStack(stack_navigators/StoresStack.js): Screens related to store lookup, such as the map screen, store list, products screen (per-store basis), and store details screen (per-store basis)
# Flow diagrams
# Customer app flow

# Clerk app flow

# Adding a new stack
TIP
Refer to documentation on adding a new stack (opens new window)
Create a new file under stack_navigators .
import { createStackNavigator } from '@react-navigation/stack';
import React from 'react';
import { Platform } from 'react-native'; // for config
import NewScreen from '{new screen path name here}';
const NewStack = createStackNavigator();
export default function NewStackNavigator() {
return (
<NewStack.Navigator
screenOptions={{
drawerLabel: 'New Screen',
headerShown: false,
cardStyle: { backgroundColor: Colors.lightest },
config,
}}>
<NewStack.Screen name="NewStuff" component={NewScreen} />
</NewStack.Navigator>
);
}
# screenOptions
drawerLabel: The label that you want to appear on the drawer in the app, if applicable (i.e. you will be adding this stack to the DrawerNavigator)
headerShown: prevents default header from being displayed in app, should set to false for style consistency purposes
config: Add this to your stack files.
const config = Platform.select({
web: { headerMode: 'screen' },
default: {
headerMode: 'none',
},
});
# NewStack.Screen
name: What you will refer to your screen as when navigating between screens in the app
component: The name of the screen component being rendered
# Adding a new screen
- Create a new screen component (i.e.
NewScreen) - Import screen to corresponding stack navigator and pass in as screen component under the stack
NOTE
We've had a lot of issues with class components conflicting with our need to use hooks (i.e. useEffect or useFocusEffect), so it would be best to make a functional component from the get-go and avoid using deprecated methods like componentWillReceiveProps in classes
# Adding a tab to the drawer (hamburger menu)
No actual edits need to be made to the HamburgerButton when changing the drawer. The drawer relies on React Navigation + Drawer, so all the button does is call toggleDrawer.
Import and pass in your new screen or stack to the DrawerNavigator
<Drawer.Screen
name="New"
component={NewStackNavigator}
options={{ title: 'New Screen', swipeEnabled: false }}
/>
NOTE
name : how we will reference the stack or screen when navigating within the app, if necessary to define
title: string that can be used as a fallback for headerTitle (docs (opens new window)), NOT to be confused with drawerLabel (we don't really need this if we don't have a header)
Styling for the drawer can be found in DrawerContent.js.
# Adding a link to the drawer
TIP
The external links in the hamburger menu can be modified without updating the code by updating the redirect URL of the short-links. See this table for a reference on the existing links in the hamburger menus.
These links are basically hardcoded and not passed in as props from the DrawerNavigator to DrawerContent. To add functional buttons (such as the LogOut button), add a styled TouchableOpacity and have it and call a function in onPress.
<TouchableOpacity
style={{ padding: 16 }}
onPress={() => action()}>
<Title>New Link</Title>
</TouchableOpacity>
Refer to "Report Issue" and "Log Out" buttons for more details in DrawerContent.
# Navigating between screens in the app
This is an example from StoreCard.js upon clicking the search bar to navigate to StoresList:
navigation.navigate('Stores', {
currentStore: store,
})
The first argument, 'Stores', is the name of the screen you want to navigate to.
The second argument refers to props we want to pass in between components. In a class component, this is accessible via this.props.route.params.
const store = this.props.route.params;
In a functional component, this is accessible via the component parameter route.
const store = route.params;
For more details on parameters in components, visit this doc (opens new window).
In a functional component, you can use the useNavigation() hook.
const navigation = useNavigation();
You can also pass navigation to a functional component as a parameter.
In classes, you can get navigation through props.
<NavButtonContainer onPress={() => this.props.navigation.goBack()}>