[react-interactions] Add DO_NOT_USE to Scope methods (#17835)
Dominic Gannaway committed
Jan 15, 2020 at 09:50 UTC
b6173e643a4311b9b1cf039824b2f3d7b974b8cf
11 files changed
+170
-157
packages/react-interactions/accessibility/README.md
-63
@@ -14,74 +14,11 @@ can be found [here](./docs).
14
15
Note: React Scopes require the internal React flag `enableScopeAPI`.
16
17
-When creating a scope, a query function is required. The query function is used
18
-when collecting host nodes that match the criteria of the query function.
19
-
20
-```jsx
21
-// This query function only matches host nodes that have the type of "div"
22
-const queryFunction = (type: string, props: Object): boolean => {
23
- if (type === 'div') {
24
- return true;
25
- }
26
- return false;
27
-};
28
-
29
-// Create the scope with the queryFunction above
30
-const DivOnlyScope = React.unstable_createScope(queryFunction);
31
-
32
-// We can now use this in our components. We need to attach
33
-// a ref so we can get the matching host nodes.
34
-function MyComponent(props) {
35
- const divOnlyScope = useRef(null);
36
- return (
37
- <DivOnlyScope ref={divOnlyScope}>
38
- <div>DIV 1</div>
39
- <div>DIV 2</div>
40
- <div>DIV 3</div>
41
- </DivOnlyScope>
42
- );
43
-}
44
-
45
-// Using the ref, we can get the host nodes via getAllNodes()
46
-const divs = divOnlyScope.current.getAllNodes();
47
-
48
-// [<div>DIV 1</div>, <div>DIV 2</div>, <div>DIV 3</div>]
49
-console.log(divs);
50
-```
51
-
17
## React Scope Interface
18
19
Scopes require a `ref` to access the internal interface of a particular scope.
20
The internal interface (`ReactScopeInterface`) exposes the following scope API:
21
57
-### getChildren: () => null | Array<ReactScopeInterface>
58
-
59
-Returns an array of all child `ReactScopeInterface` nodes that are
60
-of scopes of the same type. Returns `null` if there are no child scope nodes.
61
-
62
-### getChildrenFromRoot: () => null | Array<ReactScopeInterface>
63
-
64
-Similar to `getChildren`, except this applies the same traversal from the root of the
65
-React internal tree instead of from the scope node position.
66
-
67
-### getParent: () => null | ReactScopeInterface
68
-
69
-Returns the parent `ReactScopeInterface` of the scope node or `null` if none exists.
70
-
71
-### getProps: () => Object
72
-
73
-Returns the current `props` object of the scope node.
74
-
75
-### getAllNodes: () => null | Array<HTMLElement>
76
-
77
-Returns an array of all child host nodes that successfully match when queried using the
78
-query function passed to the scope. Returns `null` if there are no matching host nodes.
79
-
80
-### getFirstNode: () => null | HTMLElement
81
-
82
-Returns the first child host node that successfully matches when queried using the
83
-query function passed to the scope. Returns `null` if there is no matching host node.
84
-
22
### containsNode: (node: HTMLElement) => boolean
23
24
Returns `true` or `false` depending on if the given `HTMLElement` is a descendant
packages/react-interactions/accessibility/docs/TabbableScopeQuery.md
+1
-1
@@ -15,7 +15,7 @@ function FocusableNodeCollector(props) {
15
const scope = scopeRef.current;
16
17
if (scope) {
18
- const tabFocusableNodes = scope.queryAllNodes(tabbableScopeQuery);
18
+ const tabFocusableNodes = scope.DO_NOT_USE_queryAllNodes(tabbableScopeQuery);
19
if (tabFocusableNodes && props.onFocusableNodes) {
20
props.onFocusableNodes(tabFocusableNodes);
21
}
packages/react-interactions/accessibility/src/FocusContain.js
+1
-1
@@ -71,7 +71,7 @@ export default function FocusContain({
71
disabled !== true &&
72
!scope.containsNode(document.activeElement)
73
) {
74
- const fistElem = scope.queryFirstNode(scopeQuery);
74
+ const fistElem = scope.DO_NOT_USE_queryFirstNode(scopeQuery);
75
if (fistElem !== null) {
76
fistElem.focus();
77
}
packages/react-interactions/accessibility/src/FocusGroup.js
+11
-9
@@ -35,7 +35,7 @@ function focusGroupItem(
35
cell: ReactScopeMethods,
36
event: KeyboardEvent,
37
): void {
38
- const firstScopedNode = cell.queryFirstNode(scopeQuery);
38
+ const firstScopedNode = cell.DO_NOT_USE_queryFirstNode(scopeQuery);
39
if (firstScopedNode !== null) {
40
firstScopedNode.focus();
41
event.preventDefault();
@@ -46,7 +46,7 @@ function getPreviousGroupItem(
46
group: ReactScopeMethods,
47
currentItem: ReactScopeMethods,
48
): null | ReactScopeMethods {
49
- const items = group.getChildren();
49
+ const items = group.DO_NOT_USE_getChildren();
50
if (items !== null) {
51
const currentItemIndex = items.indexOf(currentItem);
52
const wrap = getGroupProps(currentItem).wrap;
@@ -63,7 +63,7 @@ function getNextGroupItem(
63
group: ReactScopeMethods,
64
currentItem: ReactScopeMethods,
65
): null | ReactScopeMethods {
66
- const items = group.getChildren();
66
+ const items = group.DO_NOT_USE_getChildren();
67
if (items !== null) {
68
const currentItemIndex = items.indexOf(currentItem);
69
const wrap = getGroupProps(currentItem).wrap;
@@ -78,9 +78,9 @@ function getNextGroupItem(
78
}
79
80
function getGroupProps(currentCell: ReactScopeMethods): Object {
81
- const group = currentCell.getParent();
81
+ const group = currentCell.DO_NOT_USE_getParent();
82
if (group !== null) {
83
- const groupProps = group.getProps();
83
+ const groupProps = group.DO_NOT_USE_getProps();
84
if (groupProps && groupProps.type === 'group') {
85
return groupProps;
86
}
@@ -125,8 +125,8 @@ export function createFocusGroup(
125
onKeyDown(event: KeyboardEvent): void {
126
const currentItem = scopeRef.current;
127
if (currentItem !== null) {
128
- const group = currentItem.getParent();
129
- const groupProps = group && group.getProps();
128
+ const group = currentItem.DO_NOT_USE_getParent();
129
+ const groupProps = group && group.DO_NOT_USE_getProps();
130
if (group !== null && groupProps.type === 'group') {
131
const portrait = groupProps.portrait;
132
const key = event.key;
@@ -134,10 +134,12 @@ export function createFocusGroup(
134
if (key === 'Tab') {
135
const tabScopeQuery = getGroupProps(currentItem).tabScopeQuery;
136
if (tabScopeQuery) {
137
- const groupScope = currentItem.getParent();
137
+ const groupScope = currentItem.DO_NOT_USE_getParent();
138
if (groupScope) {
139
const activeNode = document.activeElement;
140
- const nodes = groupScope.queryAllNodes(tabScopeQuery);
140
+ const nodes = groupScope.DO_NOT_USE_queryAllNodes(
141
+ tabScopeQuery,
142
+ );
143
for (let i = 0; i < nodes.length; i++) {
144
const node = nodes[i];
145
if (node !== activeNode) {
packages/react-interactions/accessibility/src/FocusManager.js
+3
-3
@@ -16,7 +16,7 @@ export function focusFirst(
16
scopeQuery: (type: string | Object, props: Object) => boolean,
17
scope: ReactScopeMethods,
18
): void {
19
- const firstNode = scope.queryFirstNode(scopeQuery);
19
+ const firstNode = scope.DO_NOT_USE_queryFirstNode(scopeQuery);
20
if (firstNode) {
21
focusElem(firstNode);
22
}
@@ -101,7 +101,7 @@ export function focusPrevious(
101
export function getNextScope(
102
scope: ReactScopeMethods,
103
): null | ReactScopeMethods {
104
- const allScopes = scope.getChildrenFromRoot();
104
+ const allScopes = scope.DO_NOT_USE_getChildrenFromRoot();
105
if (allScopes === null) {
106
return null;
107
}
@@ -115,7 +115,7 @@ export function getNextScope(
115
export function getPreviousScope(
116
scope: ReactScopeMethods,
117
): null | ReactScopeMethods {
118
- const allScopes = scope.getChildrenFromRoot();
118
+ const allScopes = scope.DO_NOT_USE_getChildrenFromRoot();
119
if (allScopes === null) {
120
return null;
121
}
packages/react-interactions/accessibility/src/FocusTable.js
+25
-23
@@ -42,7 +42,7 @@ function focusScope(
42
cell: ReactScopeMethods,
43
event?: KeyboardEvent,
44
): void {
45
- const firstScopedNode = cell.queryFirstNode(scopeQuery);
45
+ const firstScopedNode = cell.DO_NOT_USE_queryFirstNode(scopeQuery);
46
if (firstScopedNode !== null) {
47
firstScopedNode.focus();
48
if (event) {
@@ -58,13 +58,13 @@ function focusCellByColumnIndex(
58
columnIndex: number,
59
event?: KeyboardEvent,
60
): void {
61
- const cells = row.getChildren();
61
+ const cells = row.DO_NOT_USE_getChildren();
62
if (cells !== null) {
63
let colSize = 0;
64
for (let i = 0; i < cells.length; i++) {
65
const cell = cells[i];
66
if (cell) {
67
- colSize += cell.getProps().colSpan || 1;
67
+ colSize += cell.DO_NOT_USE_getProps().colSpan || 1;
68
if (colSize > columnIndex) {
69
focusScope(scopeQuery, cell, event);
70
return;
@@ -84,7 +84,7 @@ function getCellIndexes(
84
if (cell === currentCell) {
85
return [i, i + totalColSpan];
86
}
87
- const colSpan = cell.getProps().colSpan;
87
+ const colSpan = cell.DO_NOT_USE_getProps().colSpan;
88
if (colSpan) {
89
totalColSpan += colSpan - 1;
90
}
@@ -93,9 +93,9 @@ function getCellIndexes(
93
}
94
95
function getRowCells(currentCell: ReactScopeMethods) {
96
- const row = currentCell.getParent();
97
- if (row !== null && row.getProps().type === 'row') {
98
- const cells = row.getChildren();
96
+ const row = currentCell.DO_NOT_USE_getParent();
97
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
98
+ const cells = row.DO_NOT_USE_getChildren();
99
if (cells !== null) {
100
const [rowIndex, rowIndexWithColSpan] = getCellIndexes(
101
cells,
@@ -108,11 +108,11 @@ function getRowCells(currentCell: ReactScopeMethods) {
108
}
109
110
function getRows(currentCell: ReactScopeMethods) {
111
- const row = currentCell.getParent();
112
- if (row !== null && row.getProps().type === 'row') {
113
- const table = row.getParent();
114
- if (table !== null && table.getProps().type === 'table') {
115
- const rows = table.getChildren();
111
+ const row = currentCell.DO_NOT_USE_getParent();
112
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
113
+ const table = row.DO_NOT_USE_getParent();
114
+ if (table !== null && table.DO_NOT_USE_getProps().type === 'table') {
115
+ const rows = table.DO_NOT_USE_getChildren();
116
if (rows !== null) {
117
const columnIndex = rows.indexOf(row);
118
return [rows, columnIndex];
@@ -127,11 +127,11 @@ function triggerNavigateOut(
127
direction: 'left' | 'right' | 'up' | 'down',
128
event,
129
): void {
130
- const row = currentCell.getParent();
131
- if (row !== null && row.getProps().type === 'row') {
132
- const table = row.getParent();
130
+ const row = currentCell.DO_NOT_USE_getParent();
131
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
132
+ const table = row.DO_NOT_USE_getParent();
133
if (table !== null) {
134
- const props = table.getProps();
134
+ const props = table.DO_NOT_USE_getProps();
135
const onKeyboardOut = props.onKeyboardOut;
136
if (props.type === 'table' && typeof onKeyboardOut === 'function') {
137
onKeyboardOut(direction, event);
@@ -143,11 +143,11 @@ function triggerNavigateOut(
143
}
144
145
function getTableProps(currentCell: ReactScopeMethods): Object {
146
- const row = currentCell.getParent();
147
- if (row !== null && row.getProps().type === 'row') {
148
- const table = row.getParent();
146
+ const row = currentCell.DO_NOT_USE_getParent();
147
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
148
+ const table = row.DO_NOT_USE_getParent();
149
if (table !== null) {
150
- return table.getProps();
150
+ return table.DO_NOT_USE_getProps();
151
}
152
}
153
return {};
@@ -207,12 +207,14 @@ export function createFocusTable(
207
if (key === 'Tab') {
208
const tabScopeQuery = getTableProps(currentCell).tabScopeQuery;
209
if (tabScopeQuery) {
210
- const rowScope = currentCell.getParent();
210
+ const rowScope = currentCell.DO_NOT_USE_getParent();
211
if (rowScope) {
212
- const tableScope = rowScope.getParent();
212
+ const tableScope = rowScope.DO_NOT_USE_getParent();
213
if (tableScope) {
214
const activeNode = document.activeElement;
215
- const nodes = tableScope.queryAllNodes(tabScopeQuery);
215
+ const nodes = tableScope.DO_NOT_USE_queryAllNodes(
216
+ tabScopeQuery,
217
+ );
218
for (let i = 0; i < nodes.length; i++) {
219
const node = nodes[i];
220
if (node !== activeNode) {
packages/react-interactions/accessibility/src/__tests__/TabbableScopeQuery-test.internal.js
+2
-2
@@ -35,7 +35,7 @@ describe('TabbableScopeQuery', () => {
35
container = null;
36
});
37
38
- it('queryAllNodes() works as intended', () => {
38
+ it('DO_NOT_USE_queryAllNodes() works as intended', () => {
39
const scopeRef = React.createRef();
40
const nodeRefA = React.createRef();
41
const nodeRefB = React.createRef();
@@ -60,7 +60,7 @@ describe('TabbableScopeQuery', () => {
60
}
61
62
ReactDOM.render(<Test />, container);
63
- let nodes = scopeRef.current.queryAllNodes(tabbableScopeQuery);
63
+ let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(tabbableScopeQuery);
64
expect(nodes).toEqual([
65
nodeRefA.current,
66
nodeRefB.current,
packages/react-interactions/accessibility/src/shared/getTabbableNodes.js
+1
-1
@@ -19,7 +19,7 @@ export default function getTabbableNodes(
19
number,
20
null | HTMLElement,
21
] {
22
- const tabbableNodes = scope.queryAllNodes(scopeQuery);
22
+ const tabbableNodes = scope.DO_NOT_USE_queryAllNodes(scopeQuery);
23
if (tabbableNodes === null || tabbableNodes.length === 0) {
24
return [null, null, null, 0, null];
25
}
packages/react-reconciler/src/ReactFiberScope.js
+49
-6
@@ -12,6 +12,7 @@ import type {
12
ReactScope,
13
ReactScopeInstance,
14
ReactScopeMethods,
15
+ ReactContext,
16
} from 'shared/ReactTypes';
17
18
import {getPublicInstance, getInstanceFromNode} from './ReactFiberHostConfig';
@@ -20,6 +21,7 @@ import {
21
HostComponent,
22
SuspenseComponent,
23
ScopeComponent,
24
+ ContextProvider,
25
} from 'shared/ReactWorkTags';
26
import {enableScopeAPI} from 'shared/ReactFeatureFlags';
27
@@ -142,6 +144,38 @@ function collectNearestChildScopeMethods(
144
}
145
}
146
147
+function collectNearestContextValues<T>(
148
+ node: Fiber,
149
+ context: ReactContext<T>,
150
+ childContextValues: Array<T>,
151
+): void {
152
+ if (node.tag === ContextProvider && node.type._context === context) {
153
+ const contextValue = node.memoizedProps.value;
154
+ childContextValues.push(contextValue);
155
+ } else {
156
+ let child = node.child;
157
+
158
+ if (isFiberSuspenseAndTimedOut(node)) {
159
+ child = getSuspenseFallbackChild(node);
160
+ }
161
+ if (child !== null) {
162
+ collectNearestChildContextValues(child, context, childContextValues);
163
+ }
164
+ }
165
+}
166
+
167
+function collectNearestChildContextValues<T>(
168
+ startingChild: Fiber | null,
169
+ context: ReactContext<T>,
170
+ childContextValues: Array<T>,
171
+): void {
172
+ let child = startingChild;
173
+ while (child !== null) {
174
+ collectNearestContextValues(child, context, childContextValues);
175
+ child = child.sibling;
176
+ }
177
+}
178
+
179
function isValidScopeNode(node, scope) {
180
return (
181
node.tag === ScopeComponent &&
@@ -155,7 +189,7 @@ export function createScopeMethods(
189
instance: ReactScopeInstance,
190
): ReactScopeMethods {
191
return {
158
- getChildren(): null | Array<ReactScopeMethods> {
192
+ DO_NOT_USE_getChildren(): null | Array<ReactScopeMethods> {
193
const currentFiber = ((instance.fiber: any): Fiber);
194
const child = currentFiber.child;
195
const childrenScopes = [];
@@ -164,7 +198,7 @@ export function createScopeMethods(
198
}
199
return childrenScopes.length === 0 ? null : childrenScopes;
200
},
167
- getChildrenFromRoot(): null | Array<ReactScopeMethods> {
201
+ DO_NOT_USE_getChildrenFromRoot(): null | Array<ReactScopeMethods> {
202
const currentFiber = ((instance.fiber: any): Fiber);
203
let node = currentFiber;
204
while (node !== null) {
@@ -181,7 +215,7 @@ export function createScopeMethods(
215
collectNearestChildScopeMethods(node.child, scope, childrenScopes);
216
return childrenScopes.length === 0 ? null : childrenScopes;
217
},
184
- getParent(): null | ReactScopeMethods {
218
+ DO_NOT_USE_getParent(): null | ReactScopeMethods {
219
let node = ((instance.fiber: any): Fiber).return;
220
while (node !== null) {
221
if (node.tag === ScopeComponent && node.type === scope) {
@@ -191,11 +225,11 @@ export function createScopeMethods(
225
}
226
return null;
227
},
194
- getProps(): Object {
228
+ DO_NOT_USE_getProps(): Object {
229
const currentFiber = ((instance.fiber: any): Fiber);
230
return currentFiber.memoizedProps;
231
},
198
- queryAllNodes(
232
+ DO_NOT_USE_queryAllNodes(
233
fn: (type: string | Object, props: Object, instance: Object) => boolean,
234
): null | Array<Object> {
235
const currentFiber = ((instance.fiber: any): Fiber);
@@ -206,7 +240,7 @@ export function createScopeMethods(
240
}
241
return scopedNodes.length === 0 ? null : scopedNodes;
242
},
209
- queryFirstNode(
243
+ DO_NOT_USE_queryFirstNode(
244
fn: (type: string | Object, props: Object, instance: Object) => boolean,
245
): null | Object {
246
const currentFiber = ((instance.fiber: any): Fiber);
@@ -230,5 +264,14 @@ export function createScopeMethods(
264
}
265
return false;
266
},
267
+ getChildContextValues<T>(context: ReactContext<T>): Array<T> {
268
+ const currentFiber = ((instance.fiber: any): Fiber);
269
+ const child = currentFiber.child;
270
+ const childContextValues = [];
271
+ if (child !== null) {
272
+ collectNearestChildContextValues(child, context, childContextValues);
273
+ }
274
+ return childContextValues;
275
+ },
276
};
277
}
packages/react-reconciler/src/__tests__/ReactScope-test.internal.js
+70
-42
@@ -38,7 +38,7 @@ describe('ReactScope', () => {
38
container = null;
39
});
40
41
- it('queryAllNodes() works as intended', () => {
41
+ it('DO_NOT_USE_queryAllNodes() works as intended', () => {
42
const testScopeQuery = (type, props) => true;
43
const TestScope = React.unstable_createScope();
44
const scopeRef = React.createRef();
@@ -63,16 +63,16 @@ describe('ReactScope', () => {
63
}
64
65
ReactDOM.render(<Test toggle={true} />, container);
66
- let nodes = scopeRef.current.queryAllNodes(testScopeQuery);
66
+ let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
67
expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
68
ReactDOM.render(<Test toggle={false} />, container);
69
- nodes = scopeRef.current.queryAllNodes(testScopeQuery);
69
+ nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
70
expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
71
ReactDOM.render(null, container);
72
expect(scopeRef.current).toBe(null);
73
});
74
75
- it('queryAllNodes() provides the correct host instance', () => {
75
+ it('DO_NOT_USE_queryAllNodes() provides the correct host instance', () => {
76
const testScopeQuery = (type, props) => type === 'div';
77
const TestScope = React.unstable_createScope();
78
const scopeRef = React.createRef();
@@ -97,28 +97,28 @@ describe('ReactScope', () => {
97
}
98
99
ReactDOM.render(<Test toggle={true} />, container);
100
- let nodes = scopeRef.current.queryAllNodes(testScopeQuery);
100
+ let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
101
expect(nodes).toEqual([divRef.current]);
102
let filterQuery = (type, props, instance) =>
103
instance === spanRef.current || testScopeQuery(type, props);
104
- nodes = scopeRef.current.queryAllNodes(filterQuery);
104
+ nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);
105
expect(nodes).toEqual([divRef.current, spanRef.current]);
106
filterQuery = (type, props, instance) =>
107
[spanRef.current, aRef.current].includes(instance) ||
108
testScopeQuery(type, props);
109
- nodes = scopeRef.current.queryAllNodes(filterQuery);
109
+ nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);
110
expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
111
ReactDOM.render(<Test toggle={false} />, container);
112
filterQuery = (type, props, instance) =>
113
[spanRef.current, aRef.current].includes(instance) ||
114
testScopeQuery(type, props);
115
- nodes = scopeRef.current.queryAllNodes(filterQuery);
115
+ nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);
116
expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
117
ReactDOM.render(null, container);
118
expect(scopeRef.current).toBe(null);
119
});
120
121
- it('queryFirstNode() works as intended', () => {
121
+ it('DO_NOT_USE_queryFirstNode() works as intended', () => {
122
const testScopeQuery = (type, props) => true;
123
const TestScope = React.unstable_createScope();
124
const scopeRef = React.createRef();
@@ -143,10 +143,10 @@ describe('ReactScope', () => {
143
}
144
145
ReactDOM.render(<Test toggle={true} />, container);
146
- let node = scopeRef.current.queryFirstNode(testScopeQuery);
146
+ let node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
147
expect(node).toEqual(divRef.current);
148
ReactDOM.render(<Test toggle={false} />, container);
149
- node = scopeRef.current.queryFirstNode(testScopeQuery);
149
+ node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
150
expect(node).toEqual(aRef.current);
151
ReactDOM.render(null, container);
152
expect(scopeRef.current).toBe(null);
@@ -201,7 +201,7 @@ describe('ReactScope', () => {
201
expect(scopeRef.current.containsNode(emRef.current)).toBe(false);
202
});
203
204
- it('mixed getParent() and queryAllNodes() works as intended', () => {
204
+ it('mixed DO_NOT_USE_getParent() and queryAllNodes() works as intended', () => {
205
const testScopeQuery = (type, props) => true;
206
const TestScope = React.unstable_createScope();
207
const TestScope2 = React.unstable_createScope();
@@ -237,26 +237,26 @@ describe('ReactScope', () => {
237
}
238
239
ReactDOM.render(<Test />, container);
240
- const dParent = refD.current.getParent();
240
+ const dParent = refD.current.DO_NOT_USE_getParent();
241
expect(dParent).not.toBe(null);
242
- expect(dParent.queryAllNodes(testScopeQuery)).toEqual([
242
+ expect(dParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
243
divA.current,
244
spanB.current,
245
divB.current,
246
]);
247
- const cParent = refC.current.getParent();
247
+ const cParent = refC.current.DO_NOT_USE_getParent();
248
expect(cParent).not.toBe(null);
249
- expect(cParent.queryAllNodes(testScopeQuery)).toEqual([
249
+ expect(cParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
250
spanA.current,
251
divA.current,
252
spanB.current,
253
divB.current,
254
]);
255
- expect(refB.current.getParent()).toBe(null);
256
- expect(refA.current.getParent()).toBe(null);
255
+ expect(refB.current.DO_NOT_USE_getParent()).toBe(null);
256
+ expect(refA.current.DO_NOT_USE_getParent()).toBe(null);
257
});
258
259
- it('getChildren() works as intended', () => {
259
+ it('DO_NOT_USE_getChildren() works as intended', () => {
260
const TestScope = React.unstable_createScope();
261
const TestScope2 = React.unstable_createScope();
262
const refA = React.createRef();
@@ -291,13 +291,13 @@ describe('ReactScope', () => {
291
}
292
293
ReactDOM.render(<Test />, container);
294
- const dChildren = refD.current.getChildren();
294
+ const dChildren = refD.current.DO_NOT_USE_getChildren();
295
expect(dChildren).toBe(null);
296
- const cChildren = refC.current.getChildren();
296
+ const cChildren = refC.current.DO_NOT_USE_getChildren();
297
expect(cChildren).toBe(null);
298
- const bChildren = refB.current.getChildren();
298
+ const bChildren = refB.current.DO_NOT_USE_getChildren();
299
expect(bChildren).toEqual([refD.current]);
300
- const aChildren = refA.current.getChildren();
300
+ const aChildren = refA.current.DO_NOT_USE_getChildren();
301
expect(aChildren).toEqual([refC.current]);
302
});
303
@@ -328,7 +328,7 @@ describe('ReactScope', () => {
328
container.innerHTML = html;
329
ReactDOM.hydrate(<Test />, container);
330
const testScopeQuery = (type, props) => true;
331
- const nodes = scopeRef.current.queryAllNodes(testScopeQuery);
331
+ const nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
332
expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
333
});
334
@@ -373,6 +373,34 @@ describe('ReactScope', () => {
373
target.keydown({key: 'Q'});
374
expect(onKeyDown).toHaveBeenCalledTimes(1);
375
});
376
+
377
+ it('getChildContextValues() works as intended', () => {
378
+ const TestContext = React.createContext();
379
+ const TestScope = React.unstable_createScope();
380
+ const scopeRef = React.createRef();
381
+
382
+ function Test({toggle}) {
383
+ return toggle ? (
384
+ <TestScope ref={scopeRef}>
385
+ <TestContext.Provider value={1} />
386
+ </TestScope>
387
+ ) : (
388
+ <TestScope ref={scopeRef}>
389
+ <TestContext.Provider value={1} />
390
+ <TestContext.Provider value={2} />
391
+ </TestScope>
392
+ );
393
+ }
394
+
395
+ ReactDOM.render(<Test toggle={true} />, container);
396
+ let nodes = scopeRef.current.getChildContextValues(TestContext);
397
+ expect(nodes).toEqual([1]);
398
+ ReactDOM.render(<Test toggle={false} />, container);
399
+ nodes = scopeRef.current.getChildContextValues(TestContext);
400
+ expect(nodes).toEqual([1, 2]);
401
+ ReactDOM.render(null, container);
402
+ expect(scopeRef.current).toBe(null);
403
+ });
404
});
405
406
describe('ReactTestRenderer', () => {
@@ -382,7 +410,7 @@ describe('ReactScope', () => {
410
ReactTestRenderer = require('react-test-renderer');
411
});
412
385
- it('queryAllNodes() works as intended', () => {
413
+ it('DO_NOT_USE_queryAllNodes() works as intended', () => {
414
const testScopeQuery = (type, props) => true;
415
const TestScope = React.unstable_createScope();
416
const scopeRef = React.createRef();
@@ -411,14 +439,14 @@ describe('ReactScope', () => {
439
return element;
440
},
441
});
414
- let nodes = scopeRef.current.queryAllNodes(testScopeQuery);
442
+ let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
443
expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
444
renderer.update(<Test toggle={false} />);
417
- nodes = scopeRef.current.queryAllNodes(testScopeQuery);
445
+ nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
446
expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
447
});
448
421
- it('queryFirstNode() works as intended', () => {
449
+ it('DO_NOT_USE_queryFirstNode() works as intended', () => {
450
const testScopeQuery = (type, props) => true;
451
const TestScope = React.unstable_createScope();
452
const scopeRef = React.createRef();
@@ -447,10 +475,10 @@ describe('ReactScope', () => {
475
return element;
476
},
477
});
450
- let node = scopeRef.current.queryFirstNode(testScopeQuery);
478
+ let node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
479
expect(node).toEqual(divRef.current);
480
renderer.update(<Test toggle={false} />);
453
- node = scopeRef.current.queryFirstNode(testScopeQuery);
481
+ node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
482
expect(node).toEqual(aRef.current);
483
});
484
@@ -507,7 +535,7 @@ describe('ReactScope', () => {
535
expect(scopeRef.current.containsNode(emRef.current)).toBe(false);
536
});
537
510
- it('mixed getParent() and queryAllNodes() works as intended', () => {
538
+ it('mixed DO_NOT_USE_getParent() and DO_NOT_USE_queryAllNodes() works as intended', () => {
539
const testScopeQuery = (type, props) => true;
540
const TestScope = React.unstable_createScope();
541
const TestScope2 = React.unstable_createScope();
@@ -547,26 +575,26 @@ describe('ReactScope', () => {
575
return element;
576
},
577
});
550
- const dParent = refD.current.getParent();
578
+ const dParent = refD.current.DO_NOT_USE_getParent();
579
expect(dParent).not.toBe(null);
552
- expect(dParent.queryAllNodes(testScopeQuery)).toEqual([
580
+ expect(dParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
581
divA.current,
582
spanB.current,
583
divB.current,
584
]);
557
- const cParent = refC.current.getParent();
585
+ const cParent = refC.current.DO_NOT_USE_getParent();
586
expect(cParent).not.toBe(null);
559
- expect(cParent.queryAllNodes(testScopeQuery)).toEqual([
587
+ expect(cParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
588
spanA.current,
589
divA.current,
590
spanB.current,
591
divB.current,
592
]);
565
- expect(refB.current.getParent()).toBe(null);
566
- expect(refA.current.getParent()).toBe(null);
593
+ expect(refB.current.DO_NOT_USE_getParent()).toBe(null);
594
+ expect(refA.current.DO_NOT_USE_getParent()).toBe(null);
595
});
596
569
- it('getChildren() works as intended', () => {
597
+ it('DO_NOT_USE_getChildren() works as intended', () => {
598
const TestScope = React.unstable_createScope();
599
const TestScope2 = React.unstable_createScope();
600
const refA = React.createRef();
@@ -605,13 +633,13 @@ describe('ReactScope', () => {
633
return element;
634
},
635
});
608
- const dChildren = refD.current.getChildren();
636
+ const dChildren = refD.current.DO_NOT_USE_getChildren();
637
expect(dChildren).toBe(null);
610
- const cChildren = refC.current.getChildren();
638
+ const cChildren = refC.current.DO_NOT_USE_getChildren();
639
expect(cChildren).toBe(null);
612
- const bChildren = refB.current.getChildren();
640
+ const bChildren = refB.current.DO_NOT_USE_getChildren();
641
expect(bChildren).toEqual([refD.current]);
614
- const aChildren = refA.current.getChildren();
642
+ const aChildren = refA.current.DO_NOT_USE_getChildren();
643
expect(aChildren).toEqual([refC.current]);
644
});
645
});
packages/shared/ReactTypes.js
+7
-6
@@ -171,17 +171,18 @@ export type ReactScope = {|
171
|};
172
173
export type ReactScopeMethods = {|
174
- getChildren(): null | Array<ReactScopeMethods>,
175
- getChildrenFromRoot(): null | Array<ReactScopeMethods>,
176
- getParent(): null | ReactScopeMethods,
177
- getProps(): Object,
178
- queryAllNodes(
174
+ DO_NOT_USE_getChildren(): null | Array<ReactScopeMethods>,
175
+ DO_NOT_USE_getChildrenFromRoot(): null | Array<ReactScopeMethods>,
176
+ DO_NOT_USE_getParent(): null | ReactScopeMethods,
177
+ DO_NOT_USE_getProps(): Object,
178
+ DO_NOT_USE_queryAllNodes(
179
(type: string | Object, props: Object, instance: Object) => boolean,
180
): null | Array<Object>,
181
- queryFirstNode(
181
+ DO_NOT_USE_queryFirstNode(
182
(type: string | Object, props: Object, instance: Object) => boolean,
183
): null | Object,
184
containsNode(Object): boolean,
185
+ getChildContextValues: <T>(context: ReactContext<T>) => Array<T>,
186
|};
187
188
export type ReactScopeInstance = {|