Object based react-navigation
VM
There seems no object-based generating react-navigation. It would be good to build react-navigation based on object-based.
We recently experimented with object-based like the below.
import React from 'react';
import { Ionicons } from '@expo/vector-icons';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
import { RootAppNavigators, resolveRootRoute } from '../../react-navigation';
import { Dashboard, Hello, Settings, PersonalInfo } from '../../pages';
export const Navigation = () => {
const rootRoutes: RootAppNavigators = {
MainStack: {
container: createStackNavigator(),
props: {
initialRouteName: 'Guest',
screenOptions: {
headerShown: false,
},
},
children: {
Guest: {
container: createBottomTabNavigator(),
props: {
initialRouteName: 'Home',
screenOptions: {
headerShown: false,
tabBarLabel: 'About',
tabBarIcon: ({ color }) => <Ionicons name="person" size={24} color={color} />,
},
},
children: {
Home: {
props: {
initialParams: {},
component: Dashboard,
options: {
headerShown: true,
tabBarLabel: 'Home',
headerTitle: 'Home',
tabBarIcon: ({ color }) => <Ionicons name="home" size={24} color={color} />,
},
},
},
About: {
container: createStackNavigator(),
props: {
initialRouteName: 'Hello',
},
children: {
Hello: {
props: {
initialParams: {},
component: Hello,
options: {
headerTitle: 'About',
},
},
},
PersonalInfo: {
props: {
initialParams: { name: 'Test' },
component: PersonalInfo,
options: {
headerTitle: 'Personal Info',
},
},
},
},
},
},
},
Setting: {
props: {
initialParams: {},
component: Settings,
options: {
headerShown: true,
headerTitle: 'Settings',
headerBackTitle: 'Back',
},
},
},
},
},
};
const MainStack = resolveRootRoute(rootRoutes.MainStack, 'MainStack');
return <NavigationContainer>{MainStack}</NavigationContainer>;
};
And the Wrapper which builds is here
import React from 'react';
import { NavigatorItem, isStackOrTab } from './types';
const childrenToRoutes = (
children: { [name: string]: NavigatorItem },
parentNavigator: NavigatorItem,
parentRouteName: string,
) => Object.entries(children).map(([key, child]: any) => resolveRoute(key, child, parentNavigator, parentRouteName));
const resolveRoute = (
routeName: string | null,
route: any,
// parentNavigator: NavigatorItem,
parentNavigator: any,
parentRouteName: string,
) => {
if (isStackOrTab(route)) {
const navigatorRouteName = parentRouteName + (routeName === null ? '' : '.' + routeName);
const navigator = (
<route.container.Navigator
{...route.props}
key={navigatorRouteName}
children={childrenToRoutes(route.children, route, navigatorRouteName)}
/>
);
if (!parentNavigator) {
return navigator;
} else {
return (
<parentNavigator.container.Screen
key={navigatorRouteName}
name={navigatorRouteName}
children={() => navigator}
/>
);
}
} else {
const { component: C, ...rest } = route.props;
const screenName = parentRouteName + '.' + routeName;
return <parentNavigator.container.Screen {...rest} key={screenName} name={screenName} children={() => <C />} />;
}
};
const resolveRootRoute = (rootRoute: NavigatorItem, rootRouteName: string) =>
resolveRoute(null, rootRoute, null, rootRouteName);
export default resolveRootRoute;
Please let me know if anyone has any thoughts on improving it. Can we create this feature in the react-navigation repo itself?