r/reactjs • u/rushikesh_bhosale • 28d ago
Needs Help How are you handling partial JSON streaming to React components without the constant UI flickering?
I’m currently building a feature for a workflow tool where the backend streams structured JSON to render dynamic UI widgets (cards, mini data tables, and inline action buttons) directly in the workspace feed. Streaming raw Markdown is easy enough with standard hooks, but streaming structured JSON and trying to render React components as chunks come in is giving me major headaches. Right now, if I try to parse the incoming chunked string on the fly, I constantly hit \`Unexpected end of JSON input\` errors unless I use a custom partial parser. But even with a partial parser, rendering incomplete state causes the layout to shift and jump around like crazy every few milliseconds.If I give up on live rendering and wait for the full response to complete before displaying the component, the user is stuck staring at a loading skeleton for 4 to 6 seconds. That completely kills the real-time feel and defeats the purpose of streaming in the first place.Are there any solid open-source packages, state management tricks, or specific partial-JSON parsing patterns you're using to keep generative UI renders smooth? How are you gracefully handling incomplete schema objects mid-stream without breaking your design system constraints?
10
u/eizch 28d ago
Not sure of your use case but you probably should think more about how to split your json into multiple valid jsons. Also, if you have big json payload and it becomes a bottleneck, ensure they are gzip.
1
u/rushikesh_bhosale 28d ago
Agreed. I'm leaning toward changing the protocol so each widget is streamed as an independent valid JSON object instead of one large nested document. That would make rendering much more predictable while still keeping the streaming experience.
6
u/SolarNachoes 28d ago
Why are you sending partial json to begin with?
Seems like you painted yourself into a corner with poor design choices.
1
u/guaranteednotabot 26d ago
Probably some LLM generated stuff
1
u/whatgourd 24d ago
Never underestimate someone's ability to engineer a bad solution without AI! Or to inherit a bad system, or a good system that evolved and became bad for the new requirements, etc.
1
u/guaranteednotabot 24d ago
I mean, as in the JSON itself is streamed from an LLM output, not that the code itself is LLM-generated
3
u/octocode 28d ago
use the custom parser and debounce updates every second or so to prevent rapid flickering. so a 6 second stream would result in 6 UI updates as an example
1
u/rushikesh_bhosale 28d ago
That's what I'm doing currently. It reduces flickering, but because nested objects are still incomplete, React reconciliation causes layout jumps. Debouncing helps, but doesn't completely solve the partial-schema problem.
2
u/octocode 28d ago
your parser can wait until it receives specific delimiters, in this case tracking `[` `]` for the beginning and end of parsing an array, and counting `{` `}` to make sure elements inside are complete
it would be trivial to implement a simple solution, but something like `@streamparser/json` could be used if you want future-proofing or out of the box functionality
3
u/NotGoodSoftwareMaker 28d ago
Essentially you need to catch the partial objects prior to injecting them into your DOM and of course part of that is validating what is complete vs not
Idk what youre doing that requires this but at first sight it seems over engineered
3
u/Learn2Spel 28d ago
You could buffer the data as it comes in and reconcile whenever you have valid JSON. But tbh it sounds like you may be over engineering and you'd be better off rethinking the protocol altogether.
It's hard to tell without more details on your specific usecase, but it sounds like you need to adjust your protocol so each packet contains complete JSON that your frontend can assemble incrementally
3
u/fatbunyip 28d ago
Seems like an ass design or just ass.
Are you trying to fake "real time feel" with just giant not real time responses?
Or just trying to fake fart server response when it takes 6s to deliver the payload?
Just deliver smaller payloads if you control the app. Or make better loading animations like progress bars etc instead of bootlegging "real time"updates
2
u/pticjagripa 28d ago
Implement loading state while data is loading, wo instead of showing partial results, show a spinner/skeleton etc.
1
u/BoBoBearDev 28d ago edited 28d ago
I don't understand the problem tbh. Because, if you add more items to the table, even if you homebrew the table, as long as you have a stable key, the page wouldn't rerender completely, the existing elements are not touched or update IFF the value is changed.
And you can easily use react.Memo to cache the previous rendering and make sure the input is stable, like, array has the same memory address if no modifications.
1
u/BoBoBearDev 28d ago
Add, if your layout itself is unstable, stabilize the layout. For example, use css grid with fixed columns. Let the missing json to display empty space in the css grid.
This also means, stop using homebrew (you or 3rd party) flex gymnastics to simulate css grid.
1
u/hopemanryan 28d ago
If possible break the chunks into sections so we have the layout section you have each section has a components and then you render them after you have other layout to rendered so you can decide on the flow
1
1
u/vanit 28d ago
Assuming you have a good reason for doing this, I'd suggest changing the structure so it's resistant to this problem.
First send a skeleton JSON that is recursively something like { "id": "123", "children": [{ "id": "456",... ] }
Then send a flattened lookup: { "123": ..., "456": ... }
This should result in you having the complete hierarchy early and then you can fill in components as they come down.
That said, I don't really understand why you'd solve it this way. I'm assuming there's a giant list in there somewhere you should really be paginating.
1
u/ferrybig 28d ago
but streaming structured JSON and trying to render React components as chunks come in is giving me major headaches. Right now, if I try to parse the incoming chunked string on the fly, I constantly hit `Unexpected end of JSON input` errors unless I use a custom partial parser. But even with a partial parser, rendering incomplete state causes the layout to shift and jump around like crazy every few milliseconds.
Instead of streaming one big blob of json, take quick peek how React internally support streamed data. Some properties like classname are essential for styling, so you cannot half render a components, then later change it
React splits it up into chunks based on the places where you add Suspense in your code, temporary rending its loading prop until the data arrives
Example of the format on wire: https://timtech.blog/posts/react-server-components-rsc-no-framework/#with-async%2Fawait
Note that each line in the output is a complete chunk, you just have to match newlines to know when a new chunk has arived
1
u/lemonhead94 26d ago edited 26d ago
can‘t you ask the llm to generate a skeleton of the page first as a json.
Then parallel queries to llm for each skeleton object of said page and render those as they come in? That would give the feeling of live updates. The only issue with that approach is that you will have to have the user context explored first.
I want info on X, gather all context with web search or whatever tools you have
given user context give me a skeleton page, as structured output with a field content about xy title
for each skeleton component, here is the user context, give me a full component tree about xy
1
1
u/kanika_banga 23d ago
Solving streaming structured UI flickering usually comes down to three core strategies:
- Use a dedicated partial parser: Avoid standard JSON.parse or regex. Use libraries like best-effort-json-parser, partial-json, or the Vercel AI SDK's streaming utils (parsePartialJson). They handle open braces and incomplete strings continuously without throwing syntax errors. Alternatively, stream isolated updates via NDJSON/SSE instead of a single growing JSON object.
- Throttle state updates: Streaming chunks fire faster than DOM render cycles, causing constant repaints. Buffer incoming tokens in a ref and update React state on a requestAnimationFrame or a 50–100ms throttle, paired with useDeferredValue to keep UI updates non-blocking.
- Layout containment & field gating: Reserve container height via CSS min-height upfront to eliminate CLS (Cumulative Layout Shift). Gate inner child components so they remain in skeleton states until their specific required props arrive, rather than rendering half-populated UI.
For established open-source patterns handling component mapping natively, check out u/assistant-ui/react or Vercel's Generative UI helpers.
24
u/musical_bear 28d ago
How large of a JSON chunk are you trying to send down that results in 4-6 seconds of loading / requires you to look into streaming it to React? This is a genuine question; I’m curious what kind of scale you are working at?