mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
* 'beginLifeCycleTimer' function of ReactDebugTool.js
* 'bindAutoBindMethod' function of ReactClass.js
* 'warnNoop' function of ReactServerUpdateQueue.js
* 'getInternalInstanceReadyForUpdate' function of ReactUpdateQueue.js
* 'warnNoop' function of ReactNoopUpdateQueue.js
* 'getDeclarationErrorAddendum' function of ReactDOMComponent.js
* 'getSourceInfoErrorAddendum' function of ReactElementValidator.js
* 'getDeclarationErrorAddendum' function of instantiateReactComponent.js and ReactElementValidator.js
* 'traverseAllChildrenImpl' function of traverseAllChildren.js
* 'attachRef' function of ReactRef.js
* 'mountIndeterminateComponent' function of ReactFiberBeginWork.js
* 'createFiberFromElementType' function of ReactFiber.js
* 'getDeclarationErrorAddendum' function of ReactDOMSelect.js
* 'unmountComponentAtNode' function of ReactMount.js
* 'getDeclarationErrorAddendum' function of ReactControlledValuePropTypes.js
* 'checkRenderMessage' function of CSSPropertyOperations.js
* 'getDeclarationErrorAddendum' function of ReactDomFiberSelect.js
* 'getCurrentComponentErrorInfo' function in 'ReactElementValidator'
* 'getDeclarationErrorAddendum' function in ReactDOMFiberComponent.js
147 lines
4.1 KiB
JavaScript
147 lines
4.1 KiB
JavaScript
/**
|
|
* Copyright 2013-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
* @providesModule ReactRef
|
|
* @flow
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
var ReactOwner = require('ReactOwner');
|
|
|
|
import type { ReactInstance } from 'ReactInstanceType';
|
|
import type { ReactElement } from 'ReactElementType';
|
|
|
|
var ReactRef = {};
|
|
|
|
if (__DEV__) {
|
|
var ReactCompositeComponentTypes = require('ReactCompositeComponentTypes');
|
|
var ReactComponentTreeHook = require('ReactComponentTreeHook');
|
|
var warning = require('warning');
|
|
|
|
var warnedAboutStatelessRefs = {};
|
|
}
|
|
|
|
function attachRef(ref, component, owner) {
|
|
if (__DEV__) {
|
|
if (component._compositeType === ReactCompositeComponentTypes.StatelessFunctional) {
|
|
let info = '';
|
|
let ownerName;
|
|
if (owner) {
|
|
if (typeof owner.getName === 'function') {
|
|
ownerName = owner.getName();
|
|
}
|
|
if (ownerName) {
|
|
info += '\n\nCheck the render method of `' + ownerName + '`.';
|
|
}
|
|
}
|
|
|
|
let warningKey = ownerName || component._debugID;
|
|
let element = component._currentElement;
|
|
if (element && element._source) {
|
|
warningKey = element._source.fileName + ':' + element._source.lineNumber;
|
|
}
|
|
if (!warnedAboutStatelessRefs[warningKey]) {
|
|
warnedAboutStatelessRefs[warningKey] = true;
|
|
warning(
|
|
false,
|
|
'Stateless function components cannot be given refs. ' +
|
|
'Attempts to access this ref will fail.%s%s',
|
|
info,
|
|
ReactComponentTreeHook.getStackAddendumByID(component._debugID)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (typeof ref === 'function') {
|
|
ref(component.getPublicInstance());
|
|
} else {
|
|
// Legacy ref
|
|
ReactOwner.addComponentAsRefTo(
|
|
component,
|
|
ref,
|
|
owner,
|
|
);
|
|
}
|
|
}
|
|
|
|
function detachRef(ref, component, owner) {
|
|
if (typeof ref === 'function') {
|
|
ref(null);
|
|
} else {
|
|
// Legacy ref
|
|
ReactOwner.removeComponentAsRefFrom(component, ref, owner);
|
|
}
|
|
}
|
|
|
|
ReactRef.attachRefs = function(
|
|
instance: ReactInstance,
|
|
element: ReactElement | string | number | null | false,
|
|
): void {
|
|
if (element === null || typeof element !== 'object') {
|
|
return;
|
|
}
|
|
var ref = element.ref;
|
|
if (ref != null) {
|
|
attachRef(ref, instance, element._owner);
|
|
}
|
|
};
|
|
|
|
ReactRef.shouldUpdateRefs = function(
|
|
prevElement: ReactElement | string | number | null | false,
|
|
nextElement: ReactElement | string | number | null | false,
|
|
): boolean {
|
|
// If either the owner or a `ref` has changed, make sure the newest owner
|
|
// has stored a reference to `this`, and the previous owner (if different)
|
|
// has forgotten the reference to `this`. We use the element instead
|
|
// of the public this.props because the post processing cannot determine
|
|
// a ref. The ref conceptually lives on the element.
|
|
|
|
// TODO: Should this even be possible? The owner cannot change because
|
|
// it's forbidden by shouldUpdateReactComponent. The ref can change
|
|
// if you swap the keys of but not the refs. Reconsider where this check
|
|
// is made. It probably belongs where the key checking and
|
|
// instantiateReactComponent is done.
|
|
|
|
var prevRef = null;
|
|
var prevOwner = null;
|
|
if (prevElement !== null && typeof prevElement === 'object') {
|
|
prevRef = prevElement.ref;
|
|
prevOwner = prevElement._owner;
|
|
}
|
|
|
|
var nextRef = null;
|
|
var nextOwner = null;
|
|
if (nextElement !== null && typeof nextElement === 'object') {
|
|
nextRef = nextElement.ref;
|
|
nextOwner = nextElement._owner;
|
|
}
|
|
|
|
return (
|
|
prevRef !== nextRef ||
|
|
// If owner changes but we have an unchanged function ref, don't update refs
|
|
(typeof nextRef === 'string' && nextOwner !== prevOwner)
|
|
);
|
|
};
|
|
|
|
ReactRef.detachRefs = function(
|
|
instance: ReactInstance,
|
|
element: ReactElement | string | number | null | false,
|
|
): void {
|
|
if (element === null || typeof element !== 'object') {
|
|
return;
|
|
}
|
|
var ref = element.ref;
|
|
if (ref != null) {
|
|
detachRef(ref, instance, element._owner);
|
|
}
|
|
};
|
|
|
|
module.exports = ReactRef;
|