diff --git a/src/__tests__/index.test.tsx b/src/__tests__/index.test.tsx
index 5ca18208..395ccda6 100644
--- a/src/__tests__/index.test.tsx
+++ b/src/__tests__/index.test.tsx
@@ -189,6 +189,51 @@ it('rehydrates state for a navigator on navigation', () => {
});
});
+it('initializes state for nested screens in React.Fragment', () => {
+ const TestNavigator = (props: any) => {
+ const { state, descriptors } = useNavigationBuilder(MockRouter, props);
+
+ return descriptors[state.routes[state.index].key].render();
+ };
+
+ const TestScreen = (props: any) => {
+ React.useEffect(() => {
+ props.navigation.dispatch({ type: 'UPDATE' });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return null;
+ };
+
+ const onStateChange = jest.fn();
+
+ const element = (
+
+
+
+
+
+
+
+
+
+ );
+
+ render(element).update(element);
+
+ expect(onStateChange).toBeCalledTimes(1);
+ expect(onStateChange).toBeCalledWith({
+ index: 0,
+ key: '0',
+ routeNames: ['foo', 'bar', 'baz'],
+ routes: [
+ { key: 'foo', name: 'foo' },
+ { key: 'bar', name: 'bar' },
+ { key: 'baz', name: 'baz' },
+ ],
+ });
+});
+
it('initializes state for nested navigator on navigation', () => {
const TestNavigator = (props: any) => {
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
diff --git a/src/useNavigationBuilder.tsx b/src/useNavigationBuilder.tsx
index 2cac2f10..1ae60faa 100644
--- a/src/useNavigationBuilder.tsx
+++ b/src/useNavigationBuilder.tsx
@@ -17,19 +17,18 @@ type Options = {
const isArrayEqual = (a: any[], b: any[]) =>
a.length === b.length && a.every((it, index) => it === b[index]);
-export default function useNavigationBuilder(
- router: Router,
- options: Options
-) {
- useRegisterNavigator();
+const getRouteConfigsFromChildren = (children: React.ReactNode) =>
+ React.Children.toArray(children).reduce((acc, child) => {
+ if (React.isValidElement(child)) {
+ if (child.type === Screen) {
+ acc.push(child.props as RouteConfig);
+ return acc;
+ }
- const screens = React.Children.map(options.children, child => {
- if (child === null || child === undefined) {
- return;
- }
-
- if (React.isValidElement(child) && child.type === Screen) {
- return child.props as RouteConfig;
+ if (child.type === React.Fragment) {
+ acc.push(...getRouteConfigsFromChildren(child.props.children));
+ return acc;
+ }
}
throw new Error(
@@ -38,15 +37,21 @@ export default function useNavigationBuilder(
child.type && child.type.name ? child.type.name : String(child)
}')`
);
- })
- .filter(Boolean)
- .reduce(
- (acc, curr) => {
- acc[curr!.name] = curr as RouteConfig;
- return acc;
- },
- {} as { [key: string]: RouteConfig }
- );
+ }, []);
+
+export default function useNavigationBuilder(
+ router: Router,
+ options: Options
+) {
+ useRegisterNavigator();
+
+ const screens = getRouteConfigsFromChildren(options.children).reduce(
+ (acc, curr) => {
+ acc[curr.name] = curr;
+ return acc;
+ },
+ {} as { [key: string]: RouteConfig }
+ );
const routeNames = Object.keys(screens);
const initialRouteName =