From 166d23696cf21dd9bcf6e300cb82b178e584ebc3 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sat, 10 Mar 2018 09:17:02 -0800 Subject: [PATCH] Added invariant with component stack (in dev) for useRef without function --- .../src/ReactFiberBeginWork.js | 9 +++++- .../src/__tests__/useRef-test.internal.js | 31 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 0ccf6243d5564..d535940d06afd 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -168,7 +168,14 @@ export default function( } function updateUseRef(current, workInProgress) { - const nextChildren = workInProgress.type.renderProp( + const renderProp = workInProgress.type.renderProp; + invariant( + typeof renderProp === 'function', + 'useRef requires a render function but was given %s.%s', + renderProp === null ? 'null' : typeof renderProp, + ReactDebugCurrentFiber.getCurrentFiberStackAddendum() || '', + ); + const nextChildren = renderProp( workInProgress.pendingProps, workInProgress.ref, ); diff --git a/packages/react/src/__tests__/useRef-test.internal.js b/packages/react/src/__tests__/useRef-test.internal.js index 4e3999fbde659..8c55cc8f57a7d 100644 --- a/packages/react/src/__tests__/useRef-test.internal.js +++ b/packages/react/src/__tests__/useRef-test.internal.js @@ -14,6 +14,10 @@ describe('useRef', () => { let ReactFeatureFlags; let ReactNoop; + function normalizeCodeLocInfo(str) { + return str && str.replace(/\(at .+?:\d+\)/g, '(at **)'); + } + beforeEach(() => { jest.resetModules(); ReactFeatureFlags = require('shared/ReactFeatureFlags'); @@ -159,7 +163,7 @@ describe('useRef', () => { expect(ref.value).toBe(null); }); - it('should error if not provided a callback', () => { + it('should warn if not provided a callback during creation', () => { expect(() => React.useRef(undefined)).toWarnDev( 'useRef requires a render function but was given undefined.', ); @@ -170,4 +174,29 @@ describe('useRef', () => { 'useRef requires a render function but was given string.', ); }); + + it('should error with a callstack if rendered without a function', () => { + let RefForwardingComponent; + expect(() => { + RefForwardingComponent = React.useRef(); + }).toWarnDev('useRef requires a render function but was given undefined.'); + + ReactNoop.render( +
+ +
, + ); + + let caughtError; + try { + ReactNoop.flush(); + } catch (error) { + caughtError = error; + } + expect(caughtError).toBeDefined(); + expect(normalizeCodeLocInfo(caughtError.message)).toBe( + 'useRef requires a render function but was given undefined.' + + (__DEV__ ? '\n in div (at **)' : ''), + ); + }); });