UNPKG

1.61 kBJavaScriptView Raw
1import { options } from 'preact';
2import { assign } from './util';
3
4let oldDiffHook = options._diff;
5options._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
13export const REACT_FORWARD_SYMBOL =
14 (typeof Symbol != 'undefined' &&
15 Symbol.for &&
16 Symbol.for('react.forward_ref')) ||
17 0xf47;
18
19/**
20 * Pass ref down to a child. This is mainly used in libraries with HOCs that
21 * wrap components. Using `forwardRef` there is an easy way to get a reference
22 * of the wrapped component instead of one of the wrapper itself.
23 * @param {import('./index').ForwardFn} fn
24 * @returns {import('./internal').FunctionalComponent}
25 */
26export function forwardRef(fn) {
27 // We always have ref in props.ref, except for
28 // mobx-react. It will call this function directly
29 // and always pass ref as the second argument.
30 function Forwarded(props, ref) {
31 let clone = assign({}, props);
32 delete clone.ref;
33 ref = props.ref || ref;
34 return fn(
35 clone,
36 !ref || (typeof ref === 'object' && !('current' in ref)) ? null : ref
37 );
38 }
39
40 // mobx-react checks for this being present
41 Forwarded.$$typeof = REACT_FORWARD_SYMBOL;
42 // mobx-react heavily relies on implementation details.
43 // It expects an object here with a `render` property,
44 // and prototype.render will fail. Without this
45 // mobx-react throws.
46 Forwarded.render = Forwarded;
47
48 Forwarded.prototype.isReactComponent = Forwarded._forwarded = true;
49 Forwarded.displayName = 'ForwardRef(' + (fn.displayName || fn.name) + ')';
50 return Forwarded;
51}