diff --git a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js index 05c8b93c9ee58..a4dd86df63f21 100644 --- a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js +++ b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js @@ -78,6 +78,12 @@ exports.register = function(name: string, callback: ViewConfigGetter): string { 'Tried to register two views with the same name %s', name, ); + invariant( + typeof callback === 'function', + 'View config getter callback must be a function: %s (received %s)', + name, + callback === null ? 'null' : typeof callback, + ); viewConfigCallbacks.set(name, callback); return name; }; @@ -94,8 +100,9 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> { if (typeof callback !== 'function') { invariant( false, - 'View config not found for name %s.%s', + 'View config registration not found for name %s (received %s).%s', name, + callback === null ? 'null' : typeof callback, typeof name[0] === 'string' && /[a-z]/.test(name[0]) ? ' Make sure to start component names with a capital letter.' : '', diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js index 9abf0ee21aecb..42c07a645a7f8 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js @@ -32,6 +32,17 @@ describe('ReactNativeError', () => { .computeComponentStackForErrorReporting; }); + it('should throw error if null component registration getter is used', () => { + let error; + try { + createReactNativeComponentClass('View', null); + } catch (e) { + error = e; + } + + expect(error.toString()).toBe('Invariant Violation: View config getter callback must be a function: View (received null)'); + }); + it('should be able to extract a component stack from a native view', () => { const View = createReactNativeComponentClass('View', () => ({ validAttributes: {foo: true}, diff --git a/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js b/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js index 7290c84546c50..b43ad39ded9a2 100644 --- a/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js +++ b/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js @@ -75,6 +75,12 @@ exports.register = function(name: string, callback: ViewConfigGetter): string { 'Tried to register two views with the same name %s', name, ); + invariant( + typeof callback === 'function', + 'View config getter callback must be a function: %s (received %s)', + name, + callback === null ? 'null' : typeof callback, + ); viewConfigCallbacks.set(name, callback); return name; }; @@ -91,8 +97,9 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> { if (typeof callback !== 'function') { invariant( false, - 'View config not found for name %s.%s', + 'View config registration not found for name %s (received %s).%s', name, + callback === null ? 'null' : typeof callback, typeof name[0] === 'string' && /[a-z]/.test(name[0]) ? ' Make sure to start component names with a capital letter.' : '',