Skip to content

Commit d0d6924

Browse files
committed
Remove unnecessary try/finally blocks
To generate IDs for useId, we modify a context variable whenever multiple siblings are rendered, or when a component includes a useId hook. When this happens, we must ensure that the context is reset properly on unwind if something errors or suspends. When I originally implemented this, I did this by wrapping the child's rendering with a try/finally block. But a better way to do this is by using the non-destructive renderNode path instead of renderNodeDestructive.
1 parent b9be453 commit d0d6924

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

packages/react-server/src/ReactFizzServer.js

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,12 +1021,13 @@ function renderIndeterminateComponent(
10211021
const prevTreeContext = task.treeContext;
10221022
const totalChildren = 1;
10231023
const index = 0;
1024+
// Modify the id context. Because we'll need to reset this if something
1025+
// suspends or errors, we'll use the non-destructive render path.
10241026
task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index);
1025-
try {
1026-
renderNodeDestructive(request, task, null, value, 0);
1027-
} finally {
1028-
task.treeContext = prevTreeContext;
1029-
}
1027+
renderNode(request, task, value, 0);
1028+
// Like the other contexts, this does not need to be in a finally block
1029+
// because renderNode takes care of unwinding the stack.
1030+
task.treeContext = prevTreeContext;
10301031
} else {
10311032
renderNodeDestructive(request, task, null, value, 0);
10321033
}
@@ -1126,12 +1127,12 @@ function renderForwardRef(
11261127
const prevTreeContext = task.treeContext;
11271128
const totalChildren = 1;
11281129
const index = 0;
1130+
// Modify the id context. Because we'll need to reset this if something
1131+
// suspends or errors, we'll use the non-destructive render path.
11291132
task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index);
1130-
try {
1131-
renderNodeDestructive(request, task, null, children, 0);
1132-
} finally {
1133-
task.treeContext = prevTreeContext;
1134-
}
1133+
renderNode(request, task, children, 0);
1134+
// Like the other contexts, this does not need to be in a finally block
1135+
// because renderNode takes care of unwinding the stack.
11351136
} else {
11361137
renderNodeDestructive(request, task, null, children, 0);
11371138
}
@@ -1656,26 +1657,27 @@ function renderChildrenArray(
16561657
children: Array<any>,
16571658
childIndex: number,
16581659
) {
1659-
const prevKeyPath = task.keyPath;
1660+
const prevTreeContext = task.treeContext;
16601661
const totalChildren = children.length;
16611662
for (let i = 0; i < totalChildren; i++) {
1662-
const prevTreeContext = task.treeContext;
1663+
const node = children[i];
16631664
task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);
1664-
try {
1665-
const node = children[i];
1666-
if (isArray(node) || getIteratorFn(node)) {
1667-
// Nested arrays behave like a "fragment node" which is keyed.
1668-
// Therefore we need to add the current index as a parent key.
1669-
task.keyPath = [task.keyPath, '', childIndex];
1670-
}
1665+
if (isArray(node) || getIteratorFn(node)) {
1666+
// Nested arrays behave like a "fragment node" which is keyed.
1667+
// Therefore we need to add the current index as a parent key.
1668+
const prevKeyPath = task.keyPath;
1669+
task.keyPath = [task.keyPath, '', childIndex];
1670+
renderNode(request, task, node, i);
1671+
task.keyPath = prevKeyPath;
1672+
} else {
16711673
// We need to use the non-destructive form so that we can safely pop back
16721674
// up and render the sibling if something suspends.
16731675
renderNode(request, task, node, i);
1674-
} finally {
1675-
task.treeContext = prevTreeContext;
1676-
task.keyPath = prevKeyPath;
16771676
}
16781677
}
1678+
// Because this context is always set right before rendering every child, we
1679+
// only need to reset it to the previous value at the very end.
1680+
task.treeContext = prevTreeContext;
16791681
}
16801682

16811683
function trackPostpone(
@@ -1824,6 +1826,7 @@ function renderNode(
18241826
const previousLegacyContext = task.legacyContext;
18251827
const previousContext = task.context;
18261828
const previousKeyPath = task.keyPath;
1829+
const previousTreeContext = task.treeContext;
18271830
let previousComponentStack = null;
18281831
if (__DEV__) {
18291832
previousComponentStack = task.componentStack;
@@ -1860,6 +1863,7 @@ function renderNode(
18601863
task.legacyContext = previousLegacyContext;
18611864
task.context = previousContext;
18621865
task.keyPath = previousKeyPath;
1866+
task.treeContext = previousTreeContext;
18631867
// Restore all active ReactContexts to what they were before.
18641868
switchContext(previousContext);
18651869
if (__DEV__) {
@@ -1892,6 +1896,7 @@ function renderNode(
18921896
task.legacyContext = previousLegacyContext;
18931897
task.context = previousContext;
18941898
task.keyPath = previousKeyPath;
1899+
task.treeContext = previousTreeContext;
18951900
// Restore all active ReactContexts to what they were before.
18961901
switchContext(previousContext);
18971902
if (__DEV__) {
@@ -1906,6 +1911,7 @@ function renderNode(
19061911
task.legacyContext = previousLegacyContext;
19071912
task.context = previousContext;
19081913
task.keyPath = previousKeyPath;
1914+
task.treeContext = previousTreeContext;
19091915
// Restore all active ReactContexts to what they were before.
19101916
switchContext(previousContext);
19111917
if (__DEV__) {

0 commit comments

Comments
 (0)