From 8f764d8b0809604716d5d92ea33cc1beee02e804 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Tue, 10 Nov 2020 20:29:59 +0100 Subject: [PATCH] fix: improve the error message for incorrect screen configuration --- packages/core/src/__tests__/index.test.tsx | 45 ++++++++++++++++++++++ packages/core/src/useNavigationBuilder.tsx | 15 ++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/packages/core/src/__tests__/index.test.tsx b/packages/core/src/__tests__/index.test.tsx index 029e3fd4..f2ced483 100644 --- a/packages/core/src/__tests__/index.test.tsx +++ b/packages/core/src/__tests__/index.test.tsx @@ -1462,6 +1462,51 @@ it('throws when Screen is not the direct children', () => { ); }); +it('throws when undefined component is a direct children', () => { + const TestNavigator = (props: any) => { + useNavigationBuilder(MockRouter, props); + return null; + }; + + const Undefined = undefined; + + const spy = jest.spyOn(console, 'error').mockImplementation(); + const element = ( + + + {/* @ts-ignore */} + + + + ); + + spy.mockRestore(); + + expect(() => render(element).update(element)).toThrowError( + "A navigator can only contain 'Screen' components as its direct children (found 'undefined' for the screen 'foo')" + ); +}); + +it('throws when a tag is a direct children', () => { + const TestNavigator = (props: any) => { + useNavigationBuilder(MockRouter, props); + return null; + }; + + const element = ( + + + {/* @ts-ignore */} + + + + ); + + expect(() => render(element).update(element)).toThrowError( + "A navigator can only contain 'Screen' components as its direct children (found 'screen' for the screen 'foo')" + ); +}); + it('throws when a React Element is not the direct children', () => { const TestNavigator = (props: any) => { useNavigationBuilder(MockRouter, props); diff --git a/packages/core/src/useNavigationBuilder.tsx b/packages/core/src/useNavigationBuilder.tsx index 45f00982..3d5b0c21 100644 --- a/packages/core/src/useNavigationBuilder.tsx +++ b/packages/core/src/useNavigationBuilder.tsx @@ -90,10 +90,17 @@ const getRouteConfigsFromChildren = < } throw new Error( - `A navigator can only contain 'Screen' components as its direct children (found '${ - // @ts-expect-error: child can be any type and we're accessing it safely, but TS doesn't understand it - child.type?.name ? child.type.name : String(child) - }'). To render this component in the navigator, pass it in the 'component' prop to 'Screen'.` + `A navigator can only contain 'Screen' components as its direct children (found ${ + React.isValidElement(child) + ? `'${ + typeof child.type === 'string' ? child.type : child.type?.name + }'${ + child.props?.name ? ` for the screen '${child.props.name}'` : '' + }` + : typeof child === 'object' + ? JSON.stringify(child) + : `'${String(child)}'` + }). To render this component in the navigator, pass it in the 'component' prop to 'Screen'.` ); }, []);