-
Notifications
You must be signed in to change notification settings - Fork 50.3k
Warn for callback refs on functional components (Stack + Fiber) #8635
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
Changes from all commits
943c56e
178b4e7
3d4aa53
695f3cd
899d732
00854cf
7ac1fdd
a6752fd
ff442b6
028c651
dc1c3f8
c61ad14
9872c0d
a070e9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,7 +50,7 @@ var { | |
| var invariant = require('invariant'); | ||
|
|
||
| if (__DEV__) { | ||
| var { getCurrentFiberOwnerName } = require('ReactDebugCurrentFiber'); | ||
| var getComponentName = require('getComponentName'); | ||
| } | ||
|
|
||
| // A Fiber is work on a Component that needs to be done or was done. There can | ||
|
|
@@ -300,7 +300,12 @@ exports.createHostRootFiber = function() : Fiber { | |
| }; | ||
|
|
||
| exports.createFiberFromElement = function(element : ReactElement, priorityLevel : PriorityLevel) : Fiber { | ||
| const fiber = createFiberFromElementType(element.type, element.key); | ||
| let owner = null; | ||
| if (__DEV__) { | ||
| owner = element._owner; | ||
| } | ||
|
|
||
| const fiber = createFiberFromElementType(element.type, element.key, owner); | ||
| fiber.pendingProps = element.props; | ||
| fiber.pendingWorkPriority = priorityLevel; | ||
|
|
||
|
|
@@ -328,7 +333,7 @@ exports.createFiberFromText = function(content : string, priorityLevel : Priorit | |
| return fiber; | ||
| }; | ||
|
|
||
| function createFiberFromElementType(type : mixed, key : null | string) : Fiber { | ||
| function createFiberFromElementType(type : mixed, key : null | string, debugOwner : null | Fiber | ReactInstance) : Fiber { | ||
|
Contributor
Author
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. so the resulting fix is passing the
Collaborator
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. I couldn’t find a better solution. Using the "current fiber" was wrong here because the thing being created is the current fiber, but it's not created yet.
Contributor
Author
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. I think that makes sense. The two ideas i was going to explore was to either create something like What were the other solutions you tried that didn’t work out?
Collaborator
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. I didn't really try anything else.
The problem here is that the fiber isn't created yet so you wouldn't be able to set a reference. |
||
| let fiber; | ||
| if (typeof type === 'function') { | ||
| fiber = shouldConstruct(type) ? | ||
|
|
@@ -363,7 +368,7 @@ function createFiberFromElementType(type : mixed, key : null | string) : Fiber { | |
| ' You likely forgot to export your component from the file ' + | ||
| 'it\'s defined in.'; | ||
| } | ||
| const ownerName = getCurrentFiberOwnerName(); | ||
| const ownerName = debugOwner ? getComponentName(debugOwner) : null; | ||
| if (ownerName) { | ||
| info += ' Check the render method of `' + ownerName + '`.'; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,10 @@ describe('ReactIncrementalSideEffects', () => { | |
| ReactNoop = require('ReactNoop'); | ||
| }); | ||
|
|
||
| function normalizeCodeLocInfo(str) { | ||
| return str && str.replace(/\(at .+?:\d+\)/g, '(at **)'); | ||
| } | ||
|
|
||
| function div(...children) { | ||
| children = children.map(c => typeof c === 'string' ? { text: c } : c); | ||
| return { type: 'div', children, prop: undefined }; | ||
|
|
@@ -1069,7 +1073,7 @@ describe('ReactIncrementalSideEffects', () => { | |
| }); | ||
|
|
||
| it('invokes ref callbacks after insertion/update/unmount', () => { | ||
|
|
||
| spyOn(console, 'error'); | ||
|
Collaborator
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. If the warning wasn't intentional in this test we should fix the reason it occurs. If it was intentional we should assert on the
Contributor
Author
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. I think the warning is expected. There is a stateless component in this test that should fire a warning. I added the same warning spy that is elsewhere to this test. |
||
| var classInstance = null; | ||
|
|
||
| var ops = []; | ||
|
|
@@ -1129,6 +1133,14 @@ describe('ReactIncrementalSideEffects', () => { | |
| null, | ||
| ]); | ||
|
|
||
| expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( | ||
| 'Warning: Stateless function components cannot be given refs. ' + | ||
| 'Attempts to access this ref will fail. Check the render method ' + | ||
| 'of `Foo`.\n' + | ||
| ' in FunctionalComponent (at **)\n' + | ||
| ' in div (at **)\n' + | ||
| ' in Foo (at **)' | ||
| ); | ||
| }); | ||
|
|
||
| // TODO: Test that mounts, updates, refs, unmounts and deletions happen in the | ||
|
|
||
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.
👍 I suspected this was going to be reverted from your last comments.