I have been trying to nest multiple navigators in React Native without success.
What I want is a BottomTabsNavigator
with:
- Home
- Psalmen: regular page is grid with 150 items and when clicked goes to details
psalmen/:psalm
- Vers: click on a vers within a psalm and then you have a
MaterialTopBarNavigator
with all the verses from that psalmpsalmen/:psalm/:vers
- Vers: click on a vers within a psalm and then you have a
- Settings
EDIT For clarification: Im having trouble understandig how to set up these nested navigators with the correct types. I cam as far as getting one nested navigator to work but not more than that.
What I have now:
const BottomTabsNavigator: React.FC = () => {
return (
<BottomTabs.Navigator>
<BottomTabs.Screen name="Home" component={HomeScreen} />
<BottomTabs.Screen name="Psalmen" component={PsalmenStackNavigator} />
<BottomTabs.Screen name="Settings" component={SettingsScreen} />
</BottomTabs.Navigator>
);
};
const PsalmenStackNavigator: React.FC<PsalmenScreenProps> = () => {
const theme = useTheme();
return (
<PsalmenStack.Navigator
screenOptions={{
headerTitleStyle: { color: theme.colors.text },
headerTintColor: Platform.OS === "ios" ? theme.colors.tertiary : theme.colors.text,
}}
>
<PsalmenStack.Screen name="Psalmen" component={PsalmenScreen} />
<PsalmenStack.Screen name="Psalm" component={PsalmStackNavigator} />
</PsalmenStack.Navigator>
);
};
const PsalmStackNavigator: React.FC = () => {
return (
<PsalmStack.Navigator>
<PsalmStack.Screen name="Vers" component={VersStackNavigator} />
<PsalmStack.Screen
name="Psalm"
component={PsalmScreen}
options={({ route }) => ({
headerTitle: `Psalm ${route.params.psalm}`,
headerRight: () => <ToggleNotes />,
})}
/>
</PsalmStack.Navigator>
);
};
const VersStackNavigator: React.FC<VersStackScreenProps> = ({ route }) => {
const { psalm, vers: nummer } = route.params;
const psalmen = data as unknown as Record<string, IPsalm>;
const psalmData = psalmen[psalm.toString()];
const { verzen } = psalmData;
return (
<VersStack.Navigator>
{verzen.map(vers => (
<VersStack.Screen
name={vers.nummer.toString()}
key={`${psalm}-${vers.nummer}`}
component={VersScreen}
options={option => ({
headerTitle: `Psalm ${option.route.params.psalm}:${option.route.params.vers}`,
headerRight: () => <ToggleNotes />,
})}
/>
))}
</VersStack.Navigator>
);
};
I think my problem is in the last 2 codeblocks but I am not sure and could require some help. I'm also writing this in Typescript so I am having problems with the types aswell.
export type VersStackScreenProps = CompositeScreenProps<
NativeStackScreenProps<VersStackList, "Vers">,
PsalmScreenProps
>;
export type PsalmScreenProps = CompositeScreenProps<
NativeStackScreenProps<PsalmStackList, "Psalm">,
PsalmenScreenProps
>;
export type PsalmenScreenProps = CompositeScreenProps<
NativeStackScreenProps<PsalmenStackList, "Psalmen">,
BottomTabScreenProps<BottomTabsList>
>;
export type TabStackScreenProps<T extends keyof BottomTabsList> = BottomTabScreenProps<
BottomTabsList,
T
>;
export type BottomTabsList = {
Home: undefined;
Psalmen: NavigatorScreenParams<PsalmenStackList> | undefined;
Settings: undefined;
};
export type PsalmenStackList = {
Psalmen: undefined;
Psalm: NavigatorScreenParams<PsalmStackList> | undefined;
};
export type PsalmStackList = {
Psalm: { psalm: number };
Vers: { vers: number; psalm: number };
};
export type VersStackList = Record<string, { vers: number; psalm: number }>;