[react-interactions] Add optional searchNodes to Scope.queryAllNodes (#17293)
This commit is contained in:
parent
dee03049f5
commit
ce4b3e9981
|
@ -37,12 +37,17 @@ function collectScopedNodes(
|
||||||
node: Fiber,
|
node: Fiber,
|
||||||
fn: (type: string | Object, props: Object) => boolean,
|
fn: (type: string | Object, props: Object) => boolean,
|
||||||
scopedNodes: Array<any>,
|
scopedNodes: Array<any>,
|
||||||
|
searchNode: null | Set<Object>,
|
||||||
): void {
|
): void {
|
||||||
if (enableScopeAPI) {
|
if (enableScopeAPI) {
|
||||||
if (node.tag === HostComponent) {
|
if (node.tag === HostComponent) {
|
||||||
|
const instance = getPublicInstance(node.stateNode);
|
||||||
const {type, memoizedProps} = node;
|
const {type, memoizedProps} = node;
|
||||||
if (fn(type, memoizedProps || emptyObject) === true) {
|
if (
|
||||||
scopedNodes.push(getPublicInstance(node.stateNode));
|
(searchNode !== null && searchNode.has(instance)) ||
|
||||||
|
fn(type, memoizedProps || emptyObject) === true
|
||||||
|
) {
|
||||||
|
scopedNodes.push(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let child = node.child;
|
let child = node.child;
|
||||||
|
@ -51,7 +56,7 @@ function collectScopedNodes(
|
||||||
child = getSuspenseFallbackChild(node);
|
child = getSuspenseFallbackChild(node);
|
||||||
}
|
}
|
||||||
if (child !== null) {
|
if (child !== null) {
|
||||||
collectScopedNodesFromChildren(child, fn, scopedNodes);
|
collectScopedNodesFromChildren(child, fn, scopedNodes, searchNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,10 +88,11 @@ function collectScopedNodesFromChildren(
|
||||||
startingChild: Fiber,
|
startingChild: Fiber,
|
||||||
fn: (type: string | Object, props: Object) => boolean,
|
fn: (type: string | Object, props: Object) => boolean,
|
||||||
scopedNodes: Array<any>,
|
scopedNodes: Array<any>,
|
||||||
|
searchNode: null | Set<Object>,
|
||||||
): void {
|
): void {
|
||||||
let child = startingChild;
|
let child = startingChild;
|
||||||
while (child !== null) {
|
while (child !== null) {
|
||||||
collectScopedNodes(child, fn, scopedNodes);
|
collectScopedNodes(child, fn, scopedNodes, searchNode);
|
||||||
child = child.sibling;
|
child = child.sibling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,12 +198,14 @@ export function createScopeMethods(
|
||||||
},
|
},
|
||||||
queryAllNodes(
|
queryAllNodes(
|
||||||
fn: (type: string | Object, props: Object) => boolean,
|
fn: (type: string | Object, props: Object) => boolean,
|
||||||
|
searchNodes?: Array<Object>,
|
||||||
): null | Array<Object> {
|
): null | Array<Object> {
|
||||||
const currentFiber = ((instance.fiber: any): Fiber);
|
const currentFiber = ((instance.fiber: any): Fiber);
|
||||||
const child = currentFiber.child;
|
const child = currentFiber.child;
|
||||||
const scopedNodes = [];
|
const scopedNodes = [];
|
||||||
|
const searchNodeSet = searchNodes ? new Set(searchNodes) : null;
|
||||||
if (child !== null) {
|
if (child !== null) {
|
||||||
collectScopedNodesFromChildren(child, fn, scopedNodes);
|
collectScopedNodesFromChildren(child, fn, scopedNodes, searchNodeSet);
|
||||||
}
|
}
|
||||||
return scopedNodes.length === 0 ? null : scopedNodes;
|
return scopedNodes.length === 0 ? null : scopedNodes;
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,6 +72,50 @@ describe('ReactScope', () => {
|
||||||
expect(scopeRef.current).toBe(null);
|
expect(scopeRef.current).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('queryAllNodes() works as intended with included nodes array', () => {
|
||||||
|
const testScopeQuery = (type, props) => type === 'div';
|
||||||
|
const TestScope = React.unstable_createScope();
|
||||||
|
const scopeRef = React.createRef();
|
||||||
|
const divRef = React.createRef();
|
||||||
|
const spanRef = React.createRef();
|
||||||
|
const aRef = React.createRef();
|
||||||
|
|
||||||
|
function Test({toggle}) {
|
||||||
|
return toggle ? (
|
||||||
|
<TestScope ref={scopeRef}>
|
||||||
|
<div ref={divRef}>DIV</div>
|
||||||
|
<span ref={spanRef}>SPAN</span>
|
||||||
|
<a ref={aRef}>A</a>
|
||||||
|
</TestScope>
|
||||||
|
) : (
|
||||||
|
<TestScope ref={scopeRef}>
|
||||||
|
<a ref={aRef}>A</a>
|
||||||
|
<div ref={divRef}>DIV</div>
|
||||||
|
<span ref={spanRef}>SPAN</span>
|
||||||
|
</TestScope>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(<Test toggle={true} />, container);
|
||||||
|
let nodes = scopeRef.current.queryAllNodes(testScopeQuery);
|
||||||
|
expect(nodes).toEqual([divRef.current]);
|
||||||
|
nodes = scopeRef.current.queryAllNodes(testScopeQuery, [spanRef.current]);
|
||||||
|
expect(nodes).toEqual([divRef.current, spanRef.current]);
|
||||||
|
nodes = scopeRef.current.queryAllNodes(testScopeQuery, [
|
||||||
|
spanRef.current,
|
||||||
|
aRef.current,
|
||||||
|
]);
|
||||||
|
expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
|
||||||
|
ReactDOM.render(<Test toggle={false} />, container);
|
||||||
|
nodes = scopeRef.current.queryAllNodes(testScopeQuery, [
|
||||||
|
spanRef.current,
|
||||||
|
aRef.current,
|
||||||
|
]);
|
||||||
|
expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
|
||||||
|
ReactDOM.render(null, container);
|
||||||
|
expect(scopeRef.current).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
it('queryFirstNode() works as intended', () => {
|
it('queryFirstNode() works as intended', () => {
|
||||||
const testScopeQuery = (type, props) => true;
|
const testScopeQuery = (type, props) => true;
|
||||||
const TestScope = React.unstable_createScope();
|
const TestScope = React.unstable_createScope();
|
||||||
|
|
|
@ -171,6 +171,7 @@ export type ReactScopeMethods = {|
|
||||||
getProps(): Object,
|
getProps(): Object,
|
||||||
queryAllNodes(
|
queryAllNodes(
|
||||||
(type: string | Object, props: Object) => boolean,
|
(type: string | Object, props: Object) => boolean,
|
||||||
|
searchNodes?: Array<Object>,
|
||||||
): null | Array<Object>,
|
): null | Array<Object>,
|
||||||
queryFirstNode(
|
queryFirstNode(
|
||||||
(type: string | Object, props: Object) => boolean,
|
(type: string | Object, props: Object) => boolean,
|
||||||
|
|
Loading…
Reference in New Issue