Behavioral inconsistency in streaming logic based on root node type.
The issue describes a behavioral inconsistency in `renderToPipeableStream` where streaming starts immediately with a `div` root node but waits for Suspense resolution with a `Fragment` root node. The fix requires understanding React's streaming logic and ensuring consistent behavior regardless of root node type. The scope is somewhat clear but involves core streaming functionality.
renderToPipeableStream behaves differently if the first element is a div or a Fragment. With a div it behaves well, it starts streamming just ahead, without waiting for the promise in Suspense to fullfill. With a Fragment it doesn't behaves well, it waits for the promise in Suspense to resolve to start streamming.
React version: 19.1.0
renderToStream("div"), and then do renderToStream(React.Fragment)Link to code example:
const { renderToPipeableStream } = require("react-dom/server");
const React = require("react");
function renderToStream(Component) {
const stream = renderToPipeableStream(
React.createElement(
Component,
null,
React.createElement(
React.Suspense,
null,
new Promise((resolve) => setTimeout(resolve, 4000))
)
),
{
onShellReady() {
stream.pipe(process.stdout);
},
}
);
}
renderToStream("div"); // OK
renderToStream(React.Fragment); // NOT OK
The current behavior is WRONG with React.Fragment. Enforces users to use an unnecessary parent div if they don't want to get stuck with a blank screen.
The expected behavior is there is no difference in behaviour with React.Fragment and div. React.Fragment should start streamming immediately, as div does, and not wait for the promise in Suspense to resolve.
Claim this issue to let others know you're working on it. You'll earn 10 points when you complete it!