@samitouri / QOS-React / commits / 8f45a7fdc4

Warn about incorrect use of useImperativeHandle() (#14647)

Dan Abramov committed Jan 21, 2019 at 19:44 UTC 8f45a7fdc469c6d88ca5ca105095b03dd4e862e1
3 files changed +66
packages/react-reconciler/src/ReactFiberHooks.js
+14
@@ -674,6 +674,12 @@ export function useImperativeHandle<T>(
674 ): void {
675 if (__DEV__) {
676 currentHookNameInDev = 'useImperativeHandle';
677 + warning(
678 + typeof create === 'function',
679 + 'Expected useImperativeHandle() second argument to be a function ' +
680 + 'that creates a handle. Instead received: %s.',
681 + create !== null ? typeof create : 'null',
682 + );
683 }
684 // TODO: If deps are provided, should we skip comparing the ref itself?
685 const nextDeps =
@@ -690,6 +696,14 @@ export function useImperativeHandle<T>(
696 return () => refCallback(null);
697 } else if (ref !== null && ref !== undefined) {
698 const refObject = ref;
699 + if (__DEV__) {
700 + warning(
701 + refObject.hasOwnProperty('current'),
702 + 'Expected useImperativeHandle() first argument to either be a ' +
703 + 'ref callback or React.createRef() object. Instead received: %s.',
704 + 'an object with keys {' + Object.keys(refObject).join(', ') + '}',
705 + );
706 + }
707 const inst = create();
708 refObject.current = inst;
709 return () => {
packages/react-reconciler/src/ReactFiberScheduler.js
+13
@@ -489,6 +489,9 @@ function commitAllLifeCycles(
489 }
490 }
491 while (nextEffect !== null) {
492 + if (__DEV__) {
493 + setCurrentFiber(nextEffect);
494 + }
495 const effectTag = nextEffect.effectTag;
496
497 if (effectTag & (Update | Callback)) {
@@ -513,6 +516,9 @@ function commitAllLifeCycles(
516
517 nextEffect = nextEffect.nextEffect;
518 }
519 + if (__DEV__) {
520 + resetCurrentFiber();
521 + }
522 }
523
524 function commitPassiveEffects(root: FiberRoot, firstEffect: Fiber): void {
@@ -526,6 +532,10 @@ function commitPassiveEffects(root: FiberRoot, firstEffect: Fiber): void {
532
533 let effect = firstEffect;
534 do {
535 + if (__DEV__) {
536 + setCurrentFiber(effect);
537 + }
538 +
539 if (effect.effectTag & Passive) {
540 let didError = false;
541 let error;
@@ -549,6 +559,9 @@ function commitPassiveEffects(root: FiberRoot, firstEffect: Fiber): void {
559 }
560 effect = effect.nextEffect;
561 } while (effect !== null);
562 + if (__DEV__) {
563 + resetCurrentFiber();
564 + }
565
566 isRendering = previousIsRendering;
567
packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js
+39
@@ -569,6 +569,45 @@ describe('ReactHooks', () => {
569 ]);
570 });
571
572 + it('warns for bad useImperativeHandle first arg', () => {
573 + const {useImperativeHandle} = React;
574 + function App() {
575 + useImperativeHandle({
576 + focus() {},
577 + });
578 + return null;
579 + }
580 +
581 + expect(() => {
582 + expect(() => {
583 + ReactTestRenderer.create(<App />);
584 + }).toThrow('create is not a function');
585 + }).toWarnDev([
586 + 'Expected useImperativeHandle() first argument to either be a ' +
587 + 'ref callback or React.createRef() object. ' +
588 + 'Instead received: an object with keys {focus}.',
589 + 'Expected useImperativeHandle() second argument to be a function ' +
590 + 'that creates a handle. Instead received: undefined.',
591 + ]);
592 + });
593 +
594 + it('warns for bad useImperativeHandle second arg', () => {
595 + const {useImperativeHandle} = React;
596 + const App = React.forwardRef((props, ref) => {
597 + useImperativeHandle(ref, {
598 + focus() {},
599 + });
600 + return null;
601 + });
602 +
603 + expect(() => {
604 + ReactTestRenderer.create(<App />);
605 + }).toWarnDev([
606 + 'Expected useImperativeHandle() second argument to be a function ' +
607 + 'that creates a handle. Instead received: object.',
608 + ]);
609 + });
610 +
611 // https://github.com/facebook/react/issues/14022
612 it('works with ReactDOMServer calls inside a component', () => {
613 const {useState} = React;