ReactNative app #8 : Stack Navigation
Stack navigation is a fundamental concept in building navigation systems for mobile applications. It enables the organization of screens in a hierarchical order, resembling a stack of cards, where each screen is placed on top of the previous one. In React Native, the @react-navigation/stack library provides an intuitive way to implement stack navigation.
Installation and Setup:
Before diving into the code, let’s ensure we have the necessary dependencies installed. Run the following commands in your terminal:
1
2
npm install @react-navigation/stack
npx expo install react-native-gesture-handler
These commands install the @react-navigation/stack library and react-native-gesture-handler, a dependency required for handling gestures in React Native applications.
Creating a Stack Navigator:
Now, let’s examine how to create a stack navigator using the createStackNavigator function provided by @react-navigation/stack. Below is an example code snippet:
HomeScreenStackNav
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const Stack = createStackNavigator();
export default function HomeScreenStackNav() {
return (
<Stack.Navigator>
<Stack.Screen
name='home'
component={HomeScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name='item-list'
component={ItemList}
options={({route}) => ({title: route.params.category,
headerStyle: {
backgroundColor:'#3b82f6'
},
headerTintColor:'#fff'
})}
/>
<Stack.Screen name='product-detail'
component={ProductDetail}
options={{
headerStyle: {
backgroundColor:'#3b82f6'
},
headerTintColor:'#fff',
headerTitle:'Detail'
}}
/>
</Stack.Navigator>
)
}
Import createStackNavigator from @react-navigation/stack to create a new stack navigator. Define a Stack constant to hold the stack navigator. Within the HomeScreenStackNav function, we return the stack navigator component. Inside the
- For the ‘home’ screen, we set headerShown to false to hide the header.
- For the ‘item-list’ screen, we dynamically set the screen title based on the category parameter passed through navigation props (route.params.category). We also customize the header style and text color.
ItemList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
export default function ItemList() {
const {params} = useRoute();
const db=getFirestore(app);
const [itemList,setItemList]=useState([]);
useEffect(()=>{
params&&getItemListByCategory();
},[params])
const getItemListByCategory=async()=>{
setItemList([]);
const q=query(collection(db,'UserPost'), where('category','==', params.category));
const snapshot=await getDocs(q);
snapshot.forEach(doc=>{
setItemList(itemList=>[...itemList,doc.data()]);
})
}
return (
<View className="p-2">
{itemList?.length>0?
<LatestItemList latestItemList={itemList}
heading={''}
/>
:<Text className="p-5 text-[20px] mt-24 justify-center text-center text-gray-400">No Post Found</Text>
}
</View>
)
}
Categories
1
2
3
4
5
6
7
8
<FlatList
data={categoryList}
numColumns={4}
renderItem={({item,index})=>(
<TouchableOpacity
onPress={()=>navigation.navigate('item-list', {
category:item.name
})}
LatestItemList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default function LatestItemList({latestItemList, heading}) {
return (
<View className="mt-3">
<Text className="font-bold text-[20px]">{heading}</Text>
<FlatList
data={latestItemList}
numColumns={2}
renderItem={({item,index})=>(
<PostItem item={item} />
)}
/>
</View>
)
}
ProductDetail
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
export default function ProductDetail() {
const {params}=useRoute();
const [product,setProduct]=useState([]);
useEffect(()=> {
params&&setProduct(params.product);
},[params])
const sendEmailMessage=()=>{
const subject='Regarding '+product.title;
const body="Hi "+product.userName+"\n"+"I am insterested in this product";
Linking.openURL('mailto:'+product.userEmail+"?subject="+subject+"&body="+body);
}
return (
<ScrollView className="bg-white">
<Image source=
className="h-[320px] w-full"
/>
<View className='m-5'>
<Text className="text-[24px] font-bold">{product?.title}</Text>
<View className="items-baseline">
<Text className="bg-blue-200 p-1 mt-2 px-2 rounded-full">
{product.category}
</Text>
</View>
<Text className="mt-3 font-bold text-[20px]">Description</Text>
<Text className="text-[17px] text-gray-500">{product.desc}</Text>
</View>
{/* User info */}
<View className="p-3 flex flex-row items-center gap-3 bg-blue-100 border-gray-400">
<Image source=
className="w-12 h-12 rounded-full"
/>
<View>
<Text className="font-bold text-[18px]">{product.userName}</Text>
<Text className="text-gray-500">{product.userEmail}</Text>
</View>
</View>
<TouchableOpacity
onPress={()=>sendEmailMessage()}
className="z-40 bg-blue-500 rounded-full p-4 m-2">
<Text className="text-center text-white">Send Message</Text>
</TouchableOpacity>
</ScrollView>
)
}