-
Notifications
You must be signed in to change notification settings - Fork 46.4k
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
Move input valueTracker to DOM nodes #10208
Move input valueTracker to DOM nodes #10208
Conversation
This moves the storage of the input value tracker to the DOM node instead of the wrapperState. This makes it easier to support both Stack and Fiber without out a lot of ugly type casting and logic branches. related: facebook#10207
}, | ||
|
||
trackNode(node: ElementWithWrapperState) { | ||
_getTrackerFromInstance(inst: ReactInstance | Fiber) { | ||
return getTracker(ReactDOMComponentTree.getNodeFromInstance(inst)); |
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.
Can we not expose it? Since only tests use it and they already have access to DOM node.
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.
sure 👍
} | ||
|
||
function detachTracker(subject: SubjectWithWrapperState) { | ||
subject._wrapperState.valueTracker = null; | ||
function detachTracker(subject: ElementWithValueTracker) { |
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.
subject => node?
return false; | ||
}, | ||
|
||
stopTracking(inst: InstanceWithWrapperState | Fiber) { | ||
var tracker = getTracker(inst); | ||
updateValueIfChanged(instOrFiber: ReactInstance | Fiber) { |
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.
What do you think about always accepting nodes instead? Since we immediately get the node anyway.
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.
That's fine with me, it just means we need to call getNode at the call sites: ReactDOMComponent and ChangeEventPlugin
expect(mockComponent._wrapperState.hasOwnProperty('valueTracker')).toBe( | ||
true, | ||
); | ||
expect(node.hasOwnProperty('_valueTracker')).toBe(true); |
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.
Can also use getTracker
here?
@@ -28,128 +30,128 @@ describe('inputValueTracking', () => { | |||
mockComponent = {_hostNode: input, _wrapperState: {}}; |
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.
Can we remove mockComponent
completely?
if (inputValueTracking.updateValueIfChanged(targetInst)) { | ||
if ( | ||
inputValueTracking.updateValueIfChanged( | ||
ReactDOMComponentTree.getNodeFromInstance(targetInst), |
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.
Minor nit but it might look a bit cleaner if you extract inner expression into const targetNode = ...
@@ -109,70 +108,42 @@ function trackValueOnNode(node: any, inst: any): ?ValueTracker { | |||
|
|||
var inputValueTracking = { | |||
// exposed for testing | |||
_getTrackerFromNode(node: ElementWithWrapperState) { | |||
return getTracker(ReactDOMComponentTree.getInstanceFromNode(node)); | |||
_getTrackerFromNode(inst: ElementWithValueTracker) { |
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.
This seems like it should be node
. We can also just pass it directly: _getTrackerFromNode: getTracker
Lint reports unused stuff:
And you'll need to run |
oops sorry, my local lint is being odd. |
} | ||
|
||
if (isCheckable(node)) { | ||
value = node.checked ? 'true' : 'false'; |
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.
Is this just a stylistic change or does this affect the semantics at all?
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.
was a fight between eslint and flow. flow wants String(bool)
and eslint prohibits primitive constructors
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.
What about '' + bool
?
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.
flow complains about an invalid coercion, its being a bit over protective
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 see. I don't mind it being explicit.
Seems like we need to get CI passing and this is good to go? I'll take another look tomorrow unless someone gets ahead of me. |
function getValueFromNode(node: HTMLInputElement): string { | ||
var value = ''; | ||
if (!node) { | ||
return value; |
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.
It used to return undefined
in this code path but now returns ''
. Does this matter?
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.
@gaearon I think it's fine, getValueFromNode
is just used to compare next and last values, both of which are returned from getValueFromNode
. So the equality check should still hold.
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.
yeah the value is only ever used to compare to itself...and actually node
can't be falsely here, since it's only called below after a if (node)
check
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.
lgtm
(Please "squash and merge") |
Congratulations on first merge btw. 🥇 |
This moves the storage of the input value tracker to the DOM node
instead of the wrapperState. This makes it easier to support both Stack
and Fiber without out a lot of ugly type casting and logic branches.
related: #10207