Skip to content

Commit

Permalink
Support memo(forwardRef())
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon Dail authored and gaearon committed Mar 15, 2019
1 parent f06a74e commit 75dcd59
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 30 deletions.
19 changes: 11 additions & 8 deletions packages/react-test-renderer/src/ReactShallowRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import React from 'react';
import {isForwardRef, isMemo} from 'react-is';
import {isForwardRef, isMemo, ForwardRef} from 'react-is';
import describeComponentFrame from 'shared/describeComponentFrame';
import getComponentName from 'shared/getComponentName';
import shallowEqual from 'shared/shallowEqual';
Expand Down Expand Up @@ -589,18 +589,21 @@ class ReactShallowRenderer {
ReactCurrentDispatcher.current = this._dispatcher;
this._prepareToUseHooks(elementType);
try {
if (isForwardRef(element)) {
// elementType could still be a ForwardRef if it was
// nested inside Memo.
if (elementType.$$typeof === ForwardRef) {
invariant(
typeof elementType.render === 'function',
'forwardRef requires a render function but was given %s.',
typeof elementType.render,
);
this._rendered = elementType.render.call(
undefined,
element.props,
element.ref
element.ref,
);
} else {
this._rendered = elementType.call(
undefined,
element.props,
this._context,
);
this._rendered = elementType(element.props, this._context);
}
} finally {
ReactCurrentDispatcher.current = prevDispatcher;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1509,4 +1509,49 @@ describe('ReactShallowRenderer', () => {
shallowRenderer.render(<Foo foo={2} bar={2} />);
expect(renderCount).toBe(2);
});

it('should handle memo(forwardRef())', () => {
const testRef = React.createRef();
const SomeComponent = React.forwardRef((props, ref) => {
expect(ref).toEqual(testRef);
return (
<div>
<span className="child1" />
<span className="child2" />
</div>
);
});

const SomeMemoComponent = React.memo(SomeComponent);

const shallowRenderer = createRenderer();
const result = shallowRenderer.render(<SomeMemoComponent ref={testRef} />);

expect(result.type).toBe('div');
expect(result.props.children).toEqual([
<span className="child1" />,
<span className="child2" />,
]);
});

it('should warn for forwardRef(memo())', () => {
const testRef = React.createRef();
const SomeMemoComponent = React.memo(({foo}) => {
return <div>{foo}</div>;
});
const shallowRenderer = createRenderer();
expect(() => {
expect(() => {
const SomeComponent = React.forwardRef(SomeMemoComponent);
shallowRenderer.render(<SomeComponent ref={testRef} />);
}).toWarnDev(
'Warning: forwardRef requires a render function but received ' +
'a `memo` component. Instead of forwardRef(memo(...)), use ' +
'memo(forwardRef(...))',
{withoutStack: true},
);
}).toThrowError(
'forwardRef requires a render function but was given object.',
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -221,28 +221,6 @@ describe('ReactShallowRendererMemo', () => {
]);
});

it('should handle ForwardRef', () => {
const testRef = React.createRef();
const SomeComponent = React.forwardRef((props, ref) => {
expect(ref).toEqual(testRef);
return (
<div>
<span className="child1" />
<span className="child2" />
</div>
);
});

const shallowRenderer = createRenderer();
const result = shallowRenderer.render(<SomeComponent ref={testRef} />);

expect(result.type).toBe('div');
expect(result.props.children).toEqual([
<span className="child1" />,
<span className="child2" />,
]);
});

it('should handle Profiler', () => {
const SomeComponent = React.memo(
class SomeComponent extends React.Component {
Expand Down

0 comments on commit 75dcd59

Please sign in to comment.