-
Notifications
You must be signed in to change notification settings - Fork 48.4k
/
Copy pathReactOwner.js
118 lines (111 loc) · 3.47 KB
/
ReactOwner.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule ReactOwner
* @flow
*/
'use strict';
var invariant = require('invariant');
import type {ReactInstance} from 'ReactInstanceType';
/**
* @param {?object} object
* @return {boolean} True if `object` is a valid owner.
* @final
*/
function isValidOwner(object: any): boolean {
return !!(
object &&
typeof object.attachRef === 'function' &&
typeof object.detachRef === 'function'
);
}
/**
* ReactOwners are capable of storing references to owned components.
*
* All components are capable of //being// referenced by owner components, but
* only ReactOwner components are capable of //referencing// owned components.
* The named reference is known as a "ref".
*
* Refs are available when mounted and updated during reconciliation.
*
* var MyComponent = React.createClass({
* render: function() {
* return (
* <div onClick={this.handleClick}>
* <CustomComponent ref="custom" />
* </div>
* );
* },
* handleClick: function() {
* this.refs.custom.handleClick();
* },
* componentDidMount: function() {
* this.refs.custom.initialize();
* }
* });
*
* Refs should rarely be used. When refs are used, they should only be done to
* control data that is not handled by React's data flow.
*
* @class ReactOwner
*/
var ReactOwner = {
/**
* Adds a component by ref to an owner component.
*
* @param {ReactComponent} component Component to reference.
* @param {string} ref Name by which to refer to the component.
* @param {ReactOwner} owner Component on which to record the ref.
* @final
* @internal
*/
addComponentAsRefTo: function(
component: ReactInstance,
ref: string,
owner: ReactInstance,
): void {
invariant(
isValidOwner(owner),
'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might ' +
"be adding a ref to a component that was not created inside a component's " +
'`render` method, or you have multiple copies of React loaded ' +
'(details: https://fb.me/react-refs-must-have-owner).',
);
owner.attachRef(ref, component);
},
/**
* Removes a component by ref from an owner component.
*
* @param {ReactComponent} component Component to dereference.
* @param {string} ref Name of the ref to remove.
* @param {ReactOwner} owner Component on which the ref is recorded.
* @final
* @internal
*/
removeComponentAsRefFrom: function(
component: ReactInstance,
ref: string,
owner: ReactInstance,
): void {
invariant(
isValidOwner(owner),
'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might ' +
"be removing a ref to a component that was not created inside a component's " +
'`render` method, or you have multiple copies of React loaded ' +
'(details: https://fb.me/react-refs-must-have-owner).',
);
var ownerPublicInstance = owner.getPublicInstance();
// Check that `component`'s owner is still alive and that `component` is still the current ref
// because we do not want to detach the ref if another component stole it.
if (
ownerPublicInstance &&
ownerPublicInstance.refs[ref] === component.getPublicInstance()
) {
owner.detachRef(ref);
}
},
};
module.exports = ReactOwner;