I am trying to access the data from route.params sent from navigation screen, App is running fine but typescript conplain about my code "Property 'data' does not exist on type 'Readonly', Property 'category' does not exist on type 'Readonly'. if I console.log(route?.params?.category) & console.log(route?.params?.data) I will get the expected result. Here are my files.
types.tsx
import type { NativeStackScreenProps } from "@react-navigation/native-stack";
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
export type RootStackParamList = {
HomeScreen: undefined;
CategoryDetailScreen: { category: string };
SeachDetailScreen: { data: string[] };
};
export type RootStackScreenProps<Screen extends keyof RootStackParamList> =
NativeStackScreenProps<RootStackParamList, Screen>;
export type Props = NativeStackScreenProps<RootStackParamList>;
RootJokeStack.tsx
const RootJokeStack = () => {
return (
<JokeSearch.Navigator initialRouteName="HomeScreen">
<JokeSearch.Screen
name="HomeScreen"
component={HomeScreen}
options={() => ({
headerShown: false,
})}
/>
<JokeSearch.Screen
name="CategoryDetailScreen"
component={CategoryDetailScreen}
options={() => ({
headerShown: false,
})}
/>
<JokeSearch.Screen
name="SeachDetailScreen"
component={SeachDetailScreen}
options={() => ({
headerShown: false,
})}
/>
</JokeSearch.Navigator>
);
};
;
export default RootJokeStack;
HomeScreen.tsx
<FlatList
data={categories}
keyExtractor={(item) => item}
renderItem={({ item }) => (
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("CategoryDetailScreen", { category: item });
}}
>
<View style={styles.imageView}>
<ImageBackground
style={styles.image}
source={{
uri: "https://media.gettyimages.com/photos/chuck-norris-poses-with-two-uzis-his-sleeveless-denim-shirt-to-his-picture-id525603356",
}}
>
<View style={styles.textView}>
<Text style={{ color: colors.cardBackground }}>{item}</Text>
</View>
</ImageBackground>
</View>
</TouchableWithoutFeedback>
)}
showsVerticalScrollIndicator={false}
ListHeaderComponent={<Text style={styles.listHeader}>Categories</Text>}
horizontal={false}
numColumns={2}
/>
CategoryDetailScreen.tsx
const CategoryDetailScreen = ({ route, navigation }: Props) => {
const [categoryDetails, setcategoryDetails] = React.useState<Category>();
// console.log(route?.params?.category);
const query: string = route?.params?.category;
const getCategoryDetails = async () => {
try {
const response = await chuckNorris.get(`/random?category=${query}`);
return response.data;
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getCategoryDetails().then((data) => {
setcategoryDetails(data);
});
}, [query]);
SeachDetailScreen.tsx
const SeachDetailScreen = ({ route }: Props) => {
const query = route?.params?.data;
return (
<View style={styles.container}>
<SearchBarTitle data={query} />
<FlatList
data={query}
keyExtractor={(item) => item}
renderItem={({ item }) =>
item ? (
<View style={{ margin: 5 }}>
<Text style={{ color: "#fff", fontSize: 20 }}>{item}</Text>
</View>
) : null
}
showsVerticalScrollIndicator={false}
/>
</View>
);
};
After 23 days, I finally got solution to my question and this is how I got it fixed.
I imported the RootStackScreenProps from the type.tsx file into both the CategoryDetailScreen.tsx and SeachDetailScreen.tsx. I then replace the Props types with the RootStackScreenProps as follows and boom!!!
SeachDetailScreen.tsx
CategoryDetailScreen.tsx
Another way it could be done is to import NativeStackNavigationProp and RouteProp from @react-navigation/native-stack and @react-navigation/native respectively into type.tsx file and use it as follows. types.tsx
and then import and use StackScreenProps in SeachDetailScreen.tsx and CategoryDetailScreen.tsx to replace RootStackScreenProps. Voila!!!