diff --git a/packages/core/src/__tests__/NavigationContainer.test.tsx b/packages/core/src/__tests__/NavigationContainer.test.tsx index 54871fd7..8f9ef281 100644 --- a/packages/core/src/__tests__/NavigationContainer.test.tsx +++ b/packages/core/src/__tests__/NavigationContainer.test.tsx @@ -233,8 +233,8 @@ it('handle dispatching with ref', () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} @@ -242,8 +242,8 @@ it('handle dispatching with ref', () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} @@ -307,8 +307,8 @@ it('handle resetting state with ref', () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} @@ -316,8 +316,8 @@ it('handle resetting state with ref', () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} @@ -394,12 +394,12 @@ it('handles getRootState', () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} - null} /> + {() => null} ); diff --git a/packages/core/src/__tests__/index.test.tsx b/packages/core/src/__tests__/index.test.tsx index cf39da91..a18e8aee 100644 --- a/packages/core/src/__tests__/index.test.tsx +++ b/packages/core/src/__tests__/index.test.tsx @@ -952,7 +952,7 @@ it('throws if no name is passed to Screen', () => { ); expect(() => render(element).update(element)).toThrowError( - 'We got an invalid name (undefined) for the screen. It must be a non-empty string.' + 'Got an invalid name (undefined) for the screen. It must be a non-empty string.' ); }); @@ -971,7 +971,7 @@ it('throws if invalid name is passed to Screen', () => { ); expect(() => render(element).update(element)).toThrowError( - 'We got an invalid name ([]) for the screen. It must be a non-empty string.' + 'Got an invalid name ([]) for the screen. It must be a non-empty string.' ); }); @@ -992,7 +992,7 @@ it('throws if both children and component are passed', () => { ); expect(() => render(element).update(element)).toThrowError( - "We got both 'component' and 'children' props for the screen 'foo'. You must pass only one of them." + "Got both 'component' and 'children' props for the screen 'foo'. You must pass only one of them." ); }); @@ -1011,7 +1011,7 @@ it('throws descriptive error for undefined screen component', () => { ); expect(() => render(element).update(element)).toThrowError( - "We couldn't find a 'component' or 'children' prop for the screen 'foo'" + "Couldn't find a 'component' or 'children' prop for the screen 'foo'" ); }); @@ -1030,7 +1030,7 @@ it('throws descriptive error for invalid screen component', () => { ); expect(() => render(element).update(element)).toThrowError( - "We got an invalid value for 'component' prop for the screen 'foo'. It must be a a valid React Component." + "Got an invalid value for 'component' prop for the screen 'foo'. It must be a a valid React Component." ); }); @@ -1049,7 +1049,7 @@ it('throws descriptive error for invalid children', () => { ); expect(() => render(element).update(element)).toThrowError( - "We got an invalid value for 'children' prop for the screen 'foo'. It must be a function returning a React Element." + "Got an invalid value for 'children' prop for the screen 'foo'. It must be a function returning a React Element." ); }); diff --git a/packages/core/src/__tests__/useDescriptors.test.tsx b/packages/core/src/__tests__/useDescriptors.test.tsx index d007a140..e22ccbfe 100644 --- a/packages/core/src/__tests__/useDescriptors.test.tsx +++ b/packages/core/src/__tests__/useDescriptors.test.tsx @@ -592,7 +592,7 @@ it('returns true for canGoBack when parent router handles GO_BACK', () => { {() => ( - null} /> + {() => null} )} diff --git a/packages/core/src/__tests__/useOnAction.test.tsx b/packages/core/src/__tests__/useOnAction.test.tsx index 9cff7fe1..da072787 100644 --- a/packages/core/src/__tests__/useOnAction.test.tsx +++ b/packages/core/src/__tests__/useOnAction.test.tsx @@ -181,8 +181,8 @@ it("lets children handle the action if parent didn't", () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} @@ -291,8 +291,8 @@ it("action doesn't bubble if target is specified", () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} @@ -356,8 +356,8 @@ it('logs error if no navigator handled the action', () => { {() => ( - null} /> - null} /> + {() => null} + {() => null} )} diff --git a/packages/core/src/useNavigationBuilder.tsx b/packages/core/src/useNavigationBuilder.tsx index 601ae8b6..c54a6cce 100644 --- a/packages/core/src/useNavigationBuilder.tsx +++ b/packages/core/src/useNavigationBuilder.tsx @@ -92,7 +92,7 @@ const getRouteConfigsFromChildren = ( if (typeof name !== 'string' || !name) { throw new Error( - `We got an invalid name (${JSON.stringify( + `Got an invalid name (${JSON.stringify( name )}) for the screen. It must be a non-empty string.` ); @@ -101,24 +101,33 @@ const getRouteConfigsFromChildren = ( if (children != null || component !== undefined) { if (children != null && component !== undefined) { throw new Error( - `We got both 'component' and 'children' props for the screen '${name}'. You must pass only one of them.` + `Got both 'component' and 'children' props for the screen '${name}'. You must pass only one of them.` ); } if (children != null && typeof children !== 'function') { throw new Error( - `We got an invalid value for 'children' prop for the screen '${name}'. It must be a function returning a React Element.` + `Got an invalid value for 'children' prop for the screen '${name}'. It must be a function returning a React Element.` ); } if (component !== undefined && !isValidElementType(component)) { throw new Error( - `We got an invalid value for 'component' prop for the screen '${name}'. It must be a a valid React Component.` + `Got an invalid value for 'component' prop for the screen '${name}'. It must be a a valid React Component.` + ); + } + + if (typeof component === 'function' && component.name === 'component') { + // Inline anonymous functions passed in the `component` prop will have the name of the prop + // It's relatively safe to assume that it's not a component since it should also have PascalCase name + // We won't catch all scenarios here, but this should catch a good chunk of incorrect use. + console.warn( + `Looks like you're passing an inline function for 'component' prop for the screen '${name}' (e.g. component={() => }). Passing an inline function will cause the component state to be lost on re-render and cause perf issues since it's re-created every render. You can pass the function as children to 'Screen' instead to achieve the desired behaviour.` ); } } else { throw new Error( - `We couldn't find a 'component' or 'children' prop for the screen '${name}'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.` + `Couldn't find a 'component' or 'children' prop for the screen '${name}'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.` ); } });