( request: Request, task: Task, keyPath: KeyNode, children: ReactNodeList, hasId: boolean, actionStateCount: number, actionStateMatchingIndex: number, )
| 2569 | } |
| 2570 | |
| 2571 | function finishFunctionComponent( |
| 2572 | request: Request, |
| 2573 | task: Task, |
| 2574 | keyPath: KeyNode, |
| 2575 | children: ReactNodeList, |
| 2576 | hasId: boolean, |
| 2577 | actionStateCount: number, |
| 2578 | actionStateMatchingIndex: number, |
| 2579 | ) { |
| 2580 | let didEmitActionStateMarkers = false; |
| 2581 | if (actionStateCount !== 0 && request.formState !== null) { |
| 2582 | // For each useActionState hook, emit a marker that indicates whether we |
| 2583 | // rendered using the form state passed at the root. We only emit these |
| 2584 | // markers if form state is passed at the root. |
| 2585 | const segment = task.blockedSegment; |
| 2586 | if (segment === null) { |
| 2587 | // Implies we're in reumable mode. |
| 2588 | } else { |
| 2589 | didEmitActionStateMarkers = true; |
| 2590 | const target = segment.chunks; |
| 2591 | for (let i = 0; i < actionStateCount; i++) { |
| 2592 | if (i === actionStateMatchingIndex) { |
| 2593 | pushFormStateMarkerIsMatching(target); |
| 2594 | } else { |
| 2595 | pushFormStateMarkerIsNotMatching(target); |
| 2596 | } |
| 2597 | } |
| 2598 | } |
| 2599 | } |
| 2600 | |
| 2601 | const prevKeyPath = task.keyPath; |
| 2602 | task.keyPath = keyPath; |
| 2603 | if (hasId) { |
| 2604 | // This component materialized an id. We treat this as its own level, with |
| 2605 | // a single "child" slot. |
| 2606 | const prevTreeContext = task.treeContext; |
| 2607 | const totalChildren = 1; |
| 2608 | const index = 0; |
| 2609 | // Modify the id context. Because we'll need to reset this if something |
| 2610 | // suspends or errors, we'll use the non-destructive render path. |
| 2611 | task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index); |
| 2612 | renderNode(request, task, children, -1); |
| 2613 | // Like the other contexts, this does not need to be in a finally block |
| 2614 | // because renderNode takes care of unwinding the stack. |
| 2615 | task.treeContext = prevTreeContext; |
| 2616 | } else if (didEmitActionStateMarkers) { |
| 2617 | // If there were useActionState hooks, we must use the non-destructive path |
| 2618 | // because this component is not a pure indirection; we emitted markers |
| 2619 | // to the stream. |
| 2620 | renderNode(request, task, children, -1); |
| 2621 | } else { |
| 2622 | // We're now successfully past this task, and we haven't modified the |
| 2623 | // context stack. We don't have to pop back to the previous task every |
| 2624 | // again, so we can use the destructive recursive form. |
| 2625 | renderNodeDestructive(request, task, children, -1); |
| 2626 | } |
| 2627 | task.keyPath = prevKeyPath; |
| 2628 | } |
no test coverage detected