Skip to content

Commit 699b4b5

Browse files
committed
Forward ref by default (#4658)
* Forward ref by default * Optimizations
1 parent 756f8a7 commit 699b4b5

File tree

19 files changed

+74
-245
lines changed

19 files changed

+74
-245
lines changed

compat/src/forwardRef.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
import { options } from 'preact';
21
import { assign } from './util';
32

4-
let oldDiffHook = options._diff;
5-
options._diff = vnode => {
6-
if (vnode.type && vnode.type._forwarded && vnode.ref) {
7-
vnode.props.ref = vnode.ref;
8-
vnode.ref = null;
9-
}
10-
if (oldDiffHook) oldDiffHook(vnode);
11-
};
12-
133
export const REACT_FORWARD_SYMBOL = Symbol.for('react.forward_ref');
144

155
/**
@@ -34,7 +24,7 @@ export function forwardRef(fn) {
3424
// mobx-react throws.
3525
Forwarded.render = Forwarded;
3626

37-
Forwarded.prototype.isReactComponent = Forwarded._forwarded = true;
27+
Forwarded.prototype.isReactComponent = true;
3828
Forwarded.displayName = 'ForwardRef(' + (fn.displayName || fn.name) + ')';
3929
return Forwarded;
4030
}

compat/src/internal.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export interface Component<P = {}, S = {}> extends PreactComponent<P, S> {
2727

2828
export interface FunctionComponent<P = {}> extends PreactFunctionComponent<P> {
2929
shouldComponentUpdate?(nextProps: Readonly<P>): boolean;
30-
_forwarded?: boolean;
3130
_patchedLifecycles?: true;
3231
}
3332

compat/src/memo.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,5 @@ export function memo(c, comparer) {
2929
}
3030
Memoed.displayName = 'Memo(' + (c.displayName || c.name) + ')';
3131
Memoed.prototype.isReactComponent = true;
32-
Memoed._forwarded = true;
3332
return Memoed;
3433
}

compat/src/suspense.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,5 @@ export function lazy(loader) {
268268
}
269269

270270
Lazy.displayName = 'Lazy';
271-
Lazy._forwarded = true;
272271
return Lazy;
273272
}

compat/test/browser/forwardRef.test.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,7 @@ describe('forwardRef', () => {
402402
const Transition = ({ children }) => {
403403
const state = useState(0);
404404
forceTransition = state[1];
405-
expect(children.ref).to.not.be.undefined;
406-
if (state[0] === 0) expect(children.props.ref).to.be.undefined;
405+
expect(children.props.ref).to.not.be.undefined;
407406
return children;
408407
};
409408

compat/test/browser/memo.test.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ describe('memo()', () => {
7272

7373
let ref = null;
7474

75-
function Foo() {
75+
function Foo(props) {
7676
spy();
77-
return <h1>Hello World</h1>;
77+
return <h1 ref={props.ref}>Hello World</h1>;
7878
}
7979

8080
let Memoized = memo(Foo);
@@ -99,8 +99,7 @@ describe('memo()', () => {
9999
update();
100100
rerender();
101101

102-
expect(ref.current).not.to.be.undefined;
103-
102+
expect(ref.current).to.equal(scratch.firstChild);
104103
// TODO: not sure whether this is in-line with react...
105104
expect(spy).to.be.calledTwice;
106105
});
@@ -175,8 +174,8 @@ describe('memo()', () => {
175174

176175
it('should pass ref through nested memos', () => {
177176
class Foo extends Component {
178-
render() {
179-
return <h1>Hello World</h1>;
177+
render(props) {
178+
return <h1 ref={props.ref}>Hello World</h1>;
180179
}
181180
}
182181

@@ -187,7 +186,7 @@ describe('memo()', () => {
187186
render(<App ref={ref} />, scratch);
188187

189188
expect(ref.current).not.to.be.undefined;
190-
expect(ref.current).to.be.instanceOf(Foo);
189+
expect(ref.current).to.equal(scratch.firstChild);
191190
});
192191

193192
it('should not unnecessarily reorder children #2895', () => {

compat/test/browser/suspense.test.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ describe('suspense', () => {
271271
});
272272

273273
it('lazy should forward refs', () => {
274-
const LazyComp = () => <div>Hello from LazyComp</div>;
274+
const LazyComp = props => <div ref={props.ref} />;
275275
let ref = {};
276276

277277
/** @type {() => Promise<void>} */
@@ -297,7 +297,7 @@ describe('suspense', () => {
297297

298298
return resolve().then(() => {
299299
rerender();
300-
expect(ref.current.constructor).to.equal(LazyComp);
300+
expect(ref.current).to.equal(scratch.firstChild);
301301
});
302302
});
303303

@@ -1501,8 +1501,8 @@ describe('suspense', () => {
15011501

15021502
/** @type {() => void} */
15031503
let hide,
1504-
/** @type {(v) => void} */
1505-
setValue;
1504+
/** @type {(v) => void} */
1505+
setValue;
15061506

15071507
class Conditional extends Component {
15081508
constructor(props) {
@@ -1674,8 +1674,17 @@ describe('suspense', () => {
16741674

16751675
// eslint-disable-next-line react/require-render-return
16761676
class Suspender extends Component {
1677+
constructor(props) {
1678+
super(props);
1679+
this.state = { promise: new Promise(() => {}) };
1680+
if (typeof props.ref === 'function') {
1681+
props.ref(this);
1682+
} else if (props.ref) {
1683+
props.ref.current = this;
1684+
}
1685+
}
16771686
render() {
1678-
throw new Promise(() => {});
1687+
throw this.state.promise;
16791688
}
16801689
}
16811690

debug/src/debug.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
getCurrentVNode,
1212
getDisplayName
1313
} from './component-stack';
14-
import { assign, isNaN } from './util';
14+
import { isNaN } from './util';
1515

1616
const isWeakMapSupported = typeof WeakMap == 'function';
1717

@@ -229,15 +229,12 @@ export function initDebug() {
229229
}
230230
}
231231

232-
let values = vnode.props;
233-
if (vnode.type._forwarded) {
234-
values = assign({}, values);
235-
delete values.ref;
236-
}
232+
/* eslint-disable-next-line */
233+
const { ref: _ref, ...props } = vnode.props;
237234

238235
checkPropTypes(
239236
vnode.type.propTypes,
240-
values,
237+
props,
241238
'prop',
242239
getDisplayName(vnode),
243240
() => getOwnerStack(vnode)

hooks/test/browser/useContext.test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ describe('useContext', () => {
180180
let provider, subSpy;
181181

182182
function Comp() {
183+
provider = this._vnode._parent._component;
183184
const value = useContext(Context);
184185
values.push(value);
185186
return null;
@@ -188,7 +189,7 @@ describe('useContext', () => {
188189
render(<Comp />, scratch);
189190

190191
render(
191-
<Context.Provider ref={p => (provider = p)} value={42}>
192+
<Context.Provider value={42}>
192193
<Comp />
193194
</Context.Provider>,
194195
scratch
@@ -212,6 +213,7 @@ describe('useContext', () => {
212213
let provider, subSpy;
213214

214215
function Comp() {
216+
provider = this._vnode._parent._component;
215217
const value = useContext(Context);
216218
values.push(value);
217219
return null;
@@ -220,7 +222,7 @@ describe('useContext', () => {
220222
render(<Comp />, scratch);
221223

222224
render(
223-
<Context ref={p => (provider = p)} value={42}>
225+
<Context value={42}>
224226
<Comp />
225227
</Context>,
226228
scratch

jsx-runtime/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ function createVNode(type, props, key, isStaticChildren, __source, __self) {
3535
ref,
3636
i;
3737

38-
if ('ref' in normalizedProps) {
38+
if ('ref' in normalizedProps && typeof type != 'function') {
3939
normalizedProps = {};
4040
for (i in props) {
4141
if (i == 'ref') {

0 commit comments

Comments
 (0)