Skip to content

Commit

Permalink
Inline nested array iteration
Browse files Browse the repository at this point in the history
Since we know that we're not going to suspend again (we asssume the
iterator doesn't) and we know we're about to call renderChildrenArray
again. We can just do that directly instead of going through renderNode
another time.

This also helps separate these two paths a bit so it can have different
logic.
  • Loading branch information
sebmarkbage committed Sep 11, 2023
1 parent 1f03442 commit 4c17531
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions packages/react-server/src/ReactFizzServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1810,18 +1810,45 @@ function renderChildrenArray(
for (let i = 0; i < totalChildren; i++) {
const node = children[i];
task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);
if (isArray(node) || getIteratorFn(node)) {
// Nested arrays behave like a "fragment node" which is keyed.
// Therefore we need to add the current index as a parent key.

// Nested arrays behave like a "fragment node" which is keyed.
// Therefore we need to add the current index as a parent key.
// We first check if the nested nodes are arrays or iterables.

if (isArray(node)) {
const prevKeyPath = task.keyPath;
task.keyPath = [task.keyPath, '', childIndex];
renderNode(request, task, node, i);
renderChildrenArray(request, task, node, i);
task.keyPath = prevKeyPath;
} else {
// We need to use the non-destructive form so that we can safely pop back
// up and render the sibling if something suspends.
renderNode(request, task, node, i);
continue;
}

const iteratorFn = getIteratorFn(node);
if (iteratorFn) {
if (__DEV__) {
validateIterable(node, iteratorFn);
}
const iterator = iteratorFn.call(node);
if (iterator) {
let step = iterator.next();
if (!step.done) {
const prevKeyPath = task.keyPath;
task.keyPath = [task.keyPath, '', childIndex];
const nestedChildren = [];
do {
nestedChildren.push(step.value);
step = iterator.next();
} while (!step.done);
renderChildrenArray(request, task, nestedChildren, i);
task.keyPath = prevKeyPath;
}
continue;
}
}

// We need to use the non-destructive form so that we can safely pop back
// up and render the sibling if something suspends.
renderNode(request, task, node, i);
}
// Because this context is always set right before rendering every child, we
// only need to reset it to the previous value at the very end.
Expand Down

0 comments on commit 4c17531

Please sign in to comment.