mirror of
https://github.com/facebook/react.git
synced 2026-02-26 18:58:05 +00:00
Make numerical refs work in Fiber (#8334)
This commit is contained in:
@@ -384,7 +384,6 @@ src/renderers/shared/shared/event/__tests__/EventPluginHub-test.js
|
||||
|
||||
src/renderers/shared/stack/reconciler/__tests__/ReactComponent-test.js
|
||||
* should throw on invalid render targets
|
||||
* should throw when supplying a ref outside of render method
|
||||
* throws usefully when rendering badly-typed elements
|
||||
|
||||
src/renderers/shared/stack/reconciler/__tests__/ReactComponentLifeCycle-test.js
|
||||
|
||||
@@ -1019,6 +1019,7 @@ src/renderers/shared/shared/event/eventPlugins/__tests__/ResponderEventPlugin-te
|
||||
* should cancel correctly
|
||||
|
||||
src/renderers/shared/stack/reconciler/__tests__/ReactComponent-test.js
|
||||
* should throw when supplying a ref outside of render method
|
||||
* should warn when children are mutated during render
|
||||
* should warn when children are mutated during update
|
||||
* should support refs on owned components
|
||||
@@ -1234,6 +1235,7 @@ src/renderers/shared/stack/reconciler/__tests__/refs-test.js
|
||||
* always has a value for this.refs
|
||||
* ref called correctly for stateless component when __DEV__ = false
|
||||
* ref called correctly for stateless component when __DEV__ = true
|
||||
* coerces numbers to strings
|
||||
|
||||
src/renderers/shared/utils/__tests__/accumulateInto-test.js
|
||||
* throws if the second item is null
|
||||
|
||||
@@ -60,16 +60,16 @@ const {
|
||||
Deletion,
|
||||
} = ReactTypeOfSideEffect;
|
||||
|
||||
function transferRef(current: ?Fiber, workInProgress: Fiber, element: ReactElement<any>) {
|
||||
if (typeof element.ref === 'string') {
|
||||
function coerceRef(current: ?Fiber, element: ReactElement<any>) {
|
||||
let mixedRef = element.ref;
|
||||
if (mixedRef != null && typeof mixedRef !== 'function') {
|
||||
if (element._owner) {
|
||||
const ownerFiber : ?Fiber = (element._owner : any);
|
||||
if (ownerFiber && ownerFiber.tag === ClassComponent) {
|
||||
const stringRef = element.ref;
|
||||
const stringRef = String(mixedRef);
|
||||
// Check if previous string ref matches new string ref
|
||||
if (current && current.ref && current.ref._stringRef === stringRef) {
|
||||
workInProgress.ref = current.ref;
|
||||
return;
|
||||
return current.ref;
|
||||
}
|
||||
const inst = ownerFiber.stateNode;
|
||||
const ref = function(value) {
|
||||
@@ -77,12 +77,11 @@ function transferRef(current: ?Fiber, workInProgress: Fiber, element: ReactEleme
|
||||
refs[stringRef] = value;
|
||||
};
|
||||
ref._stringRef = stringRef;
|
||||
workInProgress.ref = ref;
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
workInProgress.ref = element.ref;
|
||||
}
|
||||
return mixedRef;
|
||||
}
|
||||
|
||||
// This wrapper function exists because I expect to clone the code in each path
|
||||
@@ -244,13 +243,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
|
||||
if (current == null || current.type !== element.type) {
|
||||
// Insert
|
||||
const created = createFiberFromElement(element, priority);
|
||||
transferRef(current, created, element);
|
||||
created.ref = coerceRef(current, element);
|
||||
created.return = returnFiber;
|
||||
return created;
|
||||
} else {
|
||||
// Move based on index
|
||||
const existing = useFiber(current, priority);
|
||||
transferRef(current, existing, element);
|
||||
existing.ref = coerceRef(current, element);
|
||||
existing.pendingProps = element.props;
|
||||
existing.return = returnFiber;
|
||||
return existing;
|
||||
@@ -342,7 +341,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
|
||||
switch (newChild.$$typeof) {
|
||||
case REACT_ELEMENT_TYPE: {
|
||||
const created = createFiberFromElement(newChild, priority);
|
||||
transferRef(null, created, newChild);
|
||||
created.ref = coerceRef(null, newChild);
|
||||
created.return = returnFiber;
|
||||
return created;
|
||||
}
|
||||
@@ -679,7 +678,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
|
||||
if (child.type === element.type) {
|
||||
deleteRemainingChildren(returnFiber, child.sibling);
|
||||
const existing = useFiber(child, priority);
|
||||
transferRef(child, existing, element);
|
||||
existing.ref = coerceRef(child, element);
|
||||
existing.pendingProps = element.props;
|
||||
existing.return = returnFiber;
|
||||
return existing;
|
||||
@@ -694,7 +693,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
|
||||
}
|
||||
|
||||
const created = createFiberFromElement(element, priority);
|
||||
transferRef(currentFirstChild, created, element);
|
||||
created.ref = coerceRef(currentFirstChild, element);
|
||||
created.return = returnFiber;
|
||||
return created;
|
||||
}
|
||||
|
||||
@@ -897,7 +897,6 @@ describe('ReactUpdates', () => {
|
||||
|
||||
var component = ReactTestUtils.renderIntoDocument(<A />);
|
||||
|
||||
console.log('xxx', expect().toThrowError);
|
||||
expect(() => component.setState({}, 'no')).toThrowError(
|
||||
'setState(...): Expected the last optional `callback` argument ' +
|
||||
'to be a function. Instead received: string.'
|
||||
|
||||
@@ -273,4 +273,14 @@ describe('ref swapping', () => {
|
||||
testRefCall();
|
||||
__DEV__ = originalDev;
|
||||
});
|
||||
|
||||
it('coerces numbers to strings', () => {
|
||||
class A extends React.Component {
|
||||
render() {
|
||||
return <div ref={1} />;
|
||||
}
|
||||
}
|
||||
const a = ReactTestUtils.renderIntoDocument(<A />);
|
||||
expect(a.refs[1].nodeName).toBe('DIV');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user