-
Notifications
You must be signed in to change notification settings - Fork 47k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC #30: React.forwardRef implementation #12346
Merged
Merged
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
9bd0fdb
RFC 30: React.useRef
bvaughn 753dba7
Added error handling tests
bvaughn 56138d2
invariant() -> warning()
bvaughn 60efe32
Changed warning wording slightly
bvaughn 166d236
Added invariant with component stack (in dev) for useRef without func…
bvaughn 0d565b5
Renamed files useRef -> forwradRef
bvaughn 508d52e
Find and replace useRef => forwardRef
bvaughn d5a196d
Changed implementation to avoid creating a fiber
bvaughn 3583bf6
USE_REF => FORWARD_REF
bvaughn 7c3d823
Removed recursion from ReactChildFiber for forwardRef
bvaughn 2661583
Merge branch 'master' into use-ref
bvaughn 6185838
Reverted accidental line reordering
bvaughn 6d7d1ef
forwardRef is now a new fiber/type again
bvaughn 5321365
Renamed renderFn to render
bvaughn 557cd79
Removed second invariant
bvaughn 04ec720
Added forwardRef type to server renderer
bvaughn 1b1deda
Slightly beefed up SSR forwardRef test case
bvaughn b91b3a3
Symbol.for react.use_ref => react.forward_ref
bvaughn c038d89
Added test to ensure refs can be forwarded between components
bvaughn 5b5b625
Read render to prop before calling
bvaughn 2a7b3c8
Merged master
bvaughn 33bb141
Updated createRef usage to use .current
bvaughn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ import { | |
REACT_ELEMENT_TYPE, | ||
REACT_FRAGMENT_TYPE, | ||
REACT_PORTAL_TYPE, | ||
REACT_FORWARD_REF_TYPE, | ||
} from 'shared/ReactSymbols'; | ||
import { | ||
FunctionalComponent, | ||
|
@@ -466,6 +467,26 @@ function ChildReconciler(shouldTrackSideEffects) { | |
} | ||
|
||
if (typeof newChild === 'object' && newChild !== null) { | ||
if ( | ||
typeof newChild.type === 'object' && | ||
newChild.type !== null && | ||
newChild.type.$$typeof === REACT_FORWARD_REF_TYPE | ||
) { | ||
const renderFn = newChild.type.renderFn; | ||
invariant( | ||
typeof renderFn === 'function', | ||
'forwardRef requires a render function but was given %s.%s', | ||
renderFn === null ? 'null' : typeof renderFn, | ||
ReactDebugCurrentFiber.getCurrentFiberStackAddendum() || '', | ||
); | ||
|
||
return createChild( | ||
returnFiber, | ||
renderFn(newChild.props, newChild.ref), | ||
expirationTime, | ||
); | ||
} | ||
|
||
switch (newChild.$$typeof) { | ||
case REACT_ELEMENT_TYPE: { | ||
const created = createFiberFromElement( | ||
|
@@ -1128,6 +1149,32 @@ function ChildReconciler(shouldTrackSideEffects) { | |
child = child.sibling; | ||
} | ||
|
||
if ( | ||
typeof element.type === 'object' && | ||
element.type !== null && | ||
element.type.$$typeof === REACT_FORWARD_REF_TYPE | ||
) { | ||
const renderFn = element.type.renderFn; | ||
invariant( | ||
typeof renderFn === 'function', | ||
'forwardRef requires a render function but was given %s.%s', | ||
renderFn === null ? 'null' : typeof renderFn, | ||
ReactDebugCurrentFiber.getCurrentFiberStackAddendum() || '', | ||
); | ||
|
||
const newElement = renderFn(element.props, element.ref); | ||
if (newElement == null) { | ||
return null; | ||
} | ||
|
||
return reconcileSingleElement( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've tried pretty hard to avoid recursive algorithms so that we could try to inline these into hot loops instead. Would prefer a while loop. |
||
returnFiber, | ||
currentFirstChild, | ||
newElement, | ||
expirationTime, | ||
); | ||
} | ||
|
||
if (element.type === REACT_FRAGMENT_TYPE) { | ||
const created = createFiberFromFragment( | ||
element.props.children, | ||
|
@@ -1213,10 +1260,24 @@ function ChildReconciler(shouldTrackSideEffects) { | |
if ( | ||
typeof newChild === 'object' && | ||
newChild !== null && | ||
newChild.type === REACT_FRAGMENT_TYPE && | ||
newChild.key === null | ||
) { | ||
newChild = newChild.props.children; | ||
if (newChild.type === REACT_FRAGMENT_TYPE) { | ||
newChild = newChild.props.children; | ||
} else if ( | ||
typeof newChild.type === 'object' && | ||
newChild.type !== null && | ||
newChild.type.$$typeof === REACT_FORWARD_REF_TYPE | ||
) { | ||
const renderFn = newChild.type.renderFn; | ||
invariant( | ||
typeof renderFn === 'function', | ||
'forwardRef requires a render function but was given %s.%s', | ||
renderFn === null ? 'null' : typeof renderFn, | ||
ReactDebugCurrentFiber.getCurrentFiberStackAddendum() || '', | ||
); | ||
newChild = renderFn(newChild.props, newChild.ref); | ||
} | ||
} | ||
|
||
// Handle object types | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The element.type won't line up on line 1125 which means that it'll kill the state of the subtree every time this rerenders.