Making DOM updates in millisecond intervals - reactjs

Scenario:
I am building a realtime IoT dashboard that will update sensor readings in millisecond intervals (100ms).The readings are streamed over websockets.There is a central redux store which dispatches actions to update the state.
Problem:
With a handful of sensors the UI is freezing possibly the browser re-painting is getting blocked (not sure).
I did a bit of research on browser fundamentals.Came across requestAnimationFrame(rAF) and an excellant talk Jake Archibald at JSConf.There is a github issue Should React use requestAnimationFrame by default related to the same.
So my question is should I use rAF for millisecond dom updates or simply rely on react internals to update the DOM? For me the millisecond precision is crucial and can't afford to have any batching of changes happening with sensor data.
Whats the way forward ?

According to this Github issue, for non-interactive events React will process setState calls asynchronously. This means that the latest state will be rendered as soon as possible. This is as close as you can get to realtime in a browser.
If you attempt to draw every single web socket state update synchronously, you run the risk of back pressure. Generally speaking, back pressure occurs when the consumer dequeues items from a queue slower than the producer enqueues them. The buffer builds up over time, causing both a memory leak and an increasing larger delay between the item's original enqueue time and the item's dequeue time.
The ReactiveX site has a good example of back pressure - the web socket being the Observable, and React's async rendering being akin to the Sample operator.
React's asynchronous rendering handles back pressure by sampling the latest provided state at the time of rendering, meaning updates to the DOM are made as quickly as possible. React will probably be faster than trying to handle DOM updates on your own, because it only updates according to state changes - it doesn't update every element every "frame".
You should probably trust React to render ASAP with the latest data, and if the web sockets messages are occuring to quickly for the UI thread to handle, then handle them in a web worker instead.

Related

The better way to build a component displaying the states of multiple devices using React

This bounty has ended. Answers to this question are eligible for a +50 reputation bounty. Bounty grace period ends in 16 hours.
Evgen is looking for a canonical answer.
Suppose I need to make a component (using React) that displays a devices state table that displays various device attributes such as their IP address, name, etc. Polling each device takes a few seconds, so you need to display a loading indicator for each specific device in the table.
I have several ways to make a similar component:
On the server side, I can create an API endpoint (like GET /device_info) that returns data for only one requested device and make multiple parallel requests from fontend to that endpoint for each device.
I can create an API endpoint (like GET /devices_info) that returns data for the entire list of devices at once on the server and make one request to it at once for the entire list of devices from frontend.
Each method has its pros and cons:
Way one:
Prons:
Easy to make. We make a "table row" component that requests data only for the device whose data it displays. The "device table" component will consist of several "table row" components that execute multiple queries in parallel each for their own device. This is especially true if you are using libraries such as React Query or RTK Query which support this behavior out of the box;
Cons:
Many requests to the endpoint, possibly hundreds (although the number of parallel requests can be limited);
If, for some reason, synchronization of access to some shared resource on the server side is required and the server supports several workers, then synchronization between workers can be very difficult to achieve, especially if each worker is a separate process;
Way two:
Prons:
One request to the endpoint;
There are no problems with access to some shared resource, everything is controlled within a single request on the server (because guaranteed there will be one worker for the request on the server side);
Cons:
It's hard to make. Since one request essentially has several intermediate states, since polling different devices takes different times, you need to make periodic requests from the UI to get an updated state, and you also need to support an interface that will support several states for each device such as: "not pulled", "in progress", "done";
With this in mind, my questions are:
What is the better way to make described component?
Does the better way have a name? Maybe it's some kind of pattern?
Maybe you know a great book/article/post that describes a solution to a similar problem?
that displays a devices state
The component asking for a device state is so... 2010?
If your device knows its state, then have your device send its state to the component
SSE - Server Sent Events, and the EventSource API
https://developer.mozilla.org/.../API/Server-sent_events
https://developer.mozilla.org/.../API/EventSource
PS. React is your choice; I would go Native JavaScript Web Components, so you have ZERO dependencies on Frameworks or Libraries for the next 30 JavaScript years
Many moons ago, I created a dashboard with PHP backend and Web Components front-end WITHOUT SSE: https://github.com/Danny-Engelman/ITpings
(no longer maintained)
Here is a general outline of how this approach might work:
On the server side, create an API endpoint that returns data for all devices in the table.
When the component is initially loaded, make a request to this endpoint to get the initial data for all devices.
Use this data to render the table, but show a loading indicator for each device that has not yet been polled.
Use a client-side timer to periodically poll each device that is still in a loading state.
When the data for a device is returned, update the table with the new information and remove the loading indicator.
This approach minimizes the number of API requests by polling devices only when necessary, while still providing a responsive user interface that updates in real-time.
As for a name or pattern for this approach, it could be considered a form of progressive enhancement or lazy loading, where the initial data is loaded on the server-side and additional data is loaded on-demand as needed.
Both ways of making the component have their pros and cons, and the choice ultimately depends on the specific requirements and constraints of the project. However, here are some additional points to consider:
Way one:
This approach is known as "rendering by fetching" or "server-driven UI", where the server is responsible for providing the data needed to render the UI. It's a common pattern in modern web development, especially with the rise of GraphQL and serverless architectures.
The main advantage of this approach is its simplicity and modularity. Each "table row" component is responsible for fetching and displaying data for its own device, which makes it easy to reason about and test. It also allows for fine-grained caching and error handling at the component level.
The main disadvantage is the potential for network congestion and server overload, especially if there are a large number of devices to display. This can be mitigated by implementing server-side throttling and client-side caching, but it adds additional complexity.
Way two:
This approach is known as "rendering by rendering" or "client-driven UI", where the client is responsible for driving the rendering logic based on the available data. It's a more traditional approach that relies on client-side JavaScript to manipulate the DOM and update the UI.
The main advantage of this approach is its efficiency and scalability. With only one request to the server, there's less network overhead and server load. It also allows for more granular control over the UI state and transitions, which can be useful for complex interactions.
The main disadvantage is its complexity and brittleness. Managing the UI state and transitions can be difficult, especially when dealing with asynchronous data fetching and error handling. It also requires more client-side JavaScript and DOM manipulation, which can slow down the UI and increase the risk of bugs and performance issues.
In summary, both approaches have their trade-offs and should be evaluated based on the specific needs of the project. There's no one-size-fits-all solution or pattern, but there are several best practices and libraries that can help simplify the implementation and improve the user experience. Some resources to explore include:
React Query and RTK Query for data fetching and caching in React.
Suspense and Concurrent Mode for asynchronous rendering and data loading in React.
GraphQL and Apollo for server-driven data fetching and caching.
Redux and MobX for state management and data flow in React.
Progressive Web Apps (PWAs) and Service Workers for offline-first and resilient web applications.
Both approaches have their own advantages and disadvantages, and the best approach depends on the specific requirements and constraints of your project. However, given that polling each device takes a few seconds and you need to display a loading indicator for each specific device in the table, the first approach (making multiple parallel requests from frontend to an API endpoint that returns data for only one requested device) seems more suitable. This approach allows you to display a loading indicator for each specific device in the table and update each row independently as soon as the data for that device becomes available.
This approach is commonly known as "concurrent data fetching" or "parallel data fetching", and it is supported by many modern front-end libraries and frameworks, such as React Query and RTK Query. These libraries allow you to easily make multiple parallel requests and manage the caching and synchronization of the data.
To implement this approach, you can create a "table row" component that requests data only for the device whose data it displays, and the "device table" component will consist of several "table row" components that execute multiple queries in parallel each for their own device. You can also limit the number of parallel requests to avoid overloading the server.
To learn more about concurrent data fetching and its implementation using React Query or RTK Query, you can refer to their official documentation and tutorials. You can also find many articles and blog posts on this topic by searching for "concurrent data fetching" or "parallel data fetching" in Google or other search engines.

shared clock vs. internal clock in react components

I have a page with a lot of relative times (updated 4 seconds ago). I'm curious the best strategy to handle something like this. The first thought I had was to setup a context at the top level of my app that updates every second. Then all the Time components could consume that context and update on each tick. My worry here is if the top level provider is causing my app to re-render every second?
My second thought was to have the updater internal to the Time component, but then I have each Time component on the page running its own update cycle.
Any thoughts on what the most efficient way to handle this use case is?
Most efficient way to do this will be to isolate the update within the components displaying the relative time. This will ensure that only this leaf component needs to be updated, rather than the entire component tree.
If you have a huge amount of such components, you will probably want to update them relatively infrequently to avoid using up too many resources on these updates.

Should I be concerned with the rate of state change in my React Redux app?

I am implementing/evaluating a "real-time" web app using React, Redux, and Websocket. On the server, I have changes occurring to my data set at a rate of about 32 changes per second.
Each change causes an async message to the app using Websocket. The async message initiates a RECEIVE action in my redux state. State changes lead to component rendering.
My concern is that the frequency of state changes will lead to unacceptable load on the client, but I'm not sure how to characterize load against number of messages, number of components, etc.
When will this become a problem or what tools would I use to figure out if it is a problem?
Does the "shape" of my state make a difference to the rendering performance? Should I consider placing high change objects in one entity while low change objects are in another entity?
Should I focus my efforts on batching the change events so that the app can respond to a list of changes rather than each individual change (effectively reducing the rate of change on state)?
I appreciate any suggestions.
Those are actually pretty reasonable questions to be asking, and yes, those do all sound like good approaches to be looking at.
As a thought - you said your server-side data changes are occurring 32 times a second. Can that information itself be batched at all? Do you literally need to display every single update?
You may be interested in the "Performance" section of the Redux FAQ, which includes answers on "scaling" and reducing the number of store subscription updates.
Grouping your state partially based on update frequency sounds like a good idea. Components that aren't subscribed to that chunk should be able to skip updates based on React Redux's built-in shallow equality checks.
I'll toss in several additional useful links for performance-related information and libraries. My React/Redux links repo has a section on React performance, and my Redux library links repo has relevant sections on store change subscriptions and component update monitoring.

Silverlight data refresh loop

I am sure that with as many dashboard apps out there, people have come across this issue. I have a SL app that needs to loop continuously, calling a RIA service to pull in data updates, with some minimal timer delay (e.g. 3 sec). It is an MVVM solution, and the data being refreshed on the client will likely be wrapped in a PagedCollectionView.
Are there any common (tr: tried and tested) approaches to fetching the data the first time and updating/appending new data in this fashion? It is purely read-only data, there is no editing to worry about.
You should be able to use a timer (that is not set to recur) to pull the data. When the data comes back, restart the timer.

WPF Real Time Multithreaded Stock Trading Application

I am building a real-time multi-threaded application in WPF, but i am having difficulties in updating the UI.
I have a background worker thread that contains logic which determines what trades to send into the market. When a valid trade is sent to the market, i receive status updates on these trades via events in my main application window. I have other events where i receive real-time price updates.
Through these events, i upate the UI. Now it appears that i receive events so rapidly through out the application, that the UI can't keep up with the speed at which events are received - causing the UI to update slowly or not at all. Essentially the UI freezes. After all events have fired, the UI slowly becomes responsive again. Once it is fully responsive, the UI shows the data that i am expecting.
My question is, how do i get the UI to update in real-time as fast as i receive events? I have been struggling with this for a while now, so any help would be appreciated.
Thanks in advance!
Instead of having the worker thread push the updates to the UI thread via events consider having the UI thread pull (or poll) them periodically. The push method is fine in a lot of situations but has two major disadvantages that are working against you.
There is an expensive marshaling operation somewhere that is transferring execution of a method to perform the UI updates safely (at least there should be).
The worker thread gets to dictate how often the UI should update and by implication how much work it should perform. It can easily overwhelm the message pump.
I propose using a shared queue in which the worker thread will enqueue a data structure containing the update and the UI thread will dequeue and process it. You can have the UI thread poll the queue at a strategically chosen interval so that it never gets bogged down. The queue will act as the buffer instead of the UI message pump. It will shrink and grow as the amount of updates ebb and flow. Here is a simple diagram of what I am talking about.
[Worker-Thread] -> [Queue] -> [UI-Thread]
I would start with the simple queue approach first, but you could take this to the next logical step of creating a pipeline in which there are 3 threads participating in the flow of updates. The worker thread enqueues updates and the UI thread dequeues them like before. But, a new thread could be added to the mix that manages the number of updates waiting in the queue and keeps it at a manageable size. It will do this by forwarding on all updates if the queue remains small, but will switch into safe mode and start discarding the updates you can live without or combining many into one if a reasonable merge operation can be defined. Here is a simple diagram of how this pattern might work.
[Worker-Thread] -> [Queue-1] -> [Pipeline-Thread] -> [Queue-2] -> [UI-Thread]
Again, start with the simple one queue approach. If you need more control then move to the pipeline pattern. I have used both successfully.
You probably need to coalesce received events such that not every tick results in a GUI update. Batch them up if your GUI is already updating, and have the GUI process the next batch only when it's ready. If the feed is high-volume (frequently the case with active trade data updates) you will not be able to create a GUI that reflects every individual tick as its own self-contained refresh trigger.

Resources