How to have same state for all users? - reactjs

I have created a react app which listens to a stream in real time. Whenever a new stream object comes in, I fetch it and append it to my state.
So a user will see all of the stream data since that user started streaming.
Now the problem is, if a second user starts streaming at some later time, he won't see any of the data which the first user has received.
I want to make one state common for all users. So that when they plug into my stream they see the same state.
How can i do that? I am using flask API which is providing me with the stream.

If you want to show the same stream for all users/browsers you cannot do it using the frontend only, because you don't have this information. You should look into the backend side to return the same data from your API.
That's why state management frontend libraries and other frontend tools will not help you, because it works only for this particular user.

Quoting from redux.org
Centralizing your application's state and logic enables powerful capabilities like undo/redo, state persistence, and much more.
I think this is what you are looking for creating a centralized state for your users :)

Related

What is the best way to solve the problem of sending mutations from multiple browser tabs in RTK Query?

I have a simple React application that allows performing CRUD operations on various entities. It uses RTK Query to interact with the backend, and I want to utilize its built-in caching system - invalidating the cache only when a mutation is performed on an endpoint with the given tag. It works fine as long as I have only one tab open. If there are multiple users interacting with the application and one of them performs a mutation, the cache will be invalidated only in this user's browser tab. The update will not be populated to other browsers or tabs that are currently connected to the app. Each user would have to manually refresh the page after another user performed a mutation. One way to solve that is to invalidate the cache periodically, which isn't ideal, another is to force every query to re-fetch on focus, which is even worse. The best scenario would be to somehow detect that another user had sent a mutation for the given endpoint, and then invalidate the cache of this endpoint (by tags) in every other browser tab that is connected to the application. I'm looking for a solution that is better than what I've already implemented, which is the following:
There's a global component with a single websocket, which immediately connects to the backend
The backend assigns a unique identifier to the socket, saves it in a socket pool and sends back an event with the identifier
The component with the socket saves the identifier in Redux
RTK Query adds the identifier as a custom header to every request sent to the backend
The backend checks the HTTP method of the request. If it is a mutation (POST / PUT / PATCH / DELETE), it extracts the identifier from the custom header, filters the socket pool excluding the socket that has the same identifier as in the request, sends an event with the tag of the service that is being mutated to all the filtered sockets
The component's socket receives the event and uses RTK Query's invalidateTags utility function to invalidate the cache of the mutated service
Thanks to that, the whole app functions as if it was a real-time collaboration tool, where every change made by any user is immediately reflected in all the connected browser tabs. However, I think it is a bit too complicated and I feel like I'm reinventing the wheel. This scenario is surely quite popular, and there must be something that I'm missing, like an npm package that solves this problem, an RTK Query option that I've omitted, or a well-known design pattern. Of course, there are multiple packages that allow synchronizing Redux Store across multiple tabs, but that doesn't solve the problem of having multiple users connecting from different devices.
It works fine as long as I have only one tab open
JS code lives within a single tab / open page by default.
That includes JS variables and logic, and the Redux store is just another JS variable.
RTK Query is not specifically designed to interact across tabs. You'll have to write that part yourself.
If the concern is multiple users interacting with the same backend server, that's what RTK Query's polling options are for. Alternately, yeah, you could have the server send a signal via websocket to let the client know it needs to refetch data. But again, that's something you'll need to write yourself, as it's specific to the needs of your own application.

How is SyncState different from sending the entire state to the other client?

I am building a multi-player Todo app. I am sending the entire todo state to the server and the server broadcasts it to the other clients. How can I use SyncState and how will it be efficient?
In case of SyncState, we send patches for communication. Patches, in general, is just the change in the current state. This allows us to send only the required data and not the entire thing, thus reducing the size of data being transferred. Doing this also provides us with a few more benefits:
A way to track history
Snapshots can be created and traced using patches
You can refer to the talk by the creator of SyncState for more in-depth explanation of using JSON patches for building multi-user apps.

Redux Online/Offline Sync for Get/Update Data

I'm working with React-Redux and I've been looking at libraries to manage to sync my data with the server. I've seen libraries like react-offline and react-persist that handle parts of my problem, but not all of it. I have these requirements:
I have control of the API, so I can change it in any way necessary
I don't want to send the entire data set to the client. Users will only have access to a subset of the data in the database
I want the application to be able to be disconnected from the internet and still run normally (the area it functions in might are spotty, or totally disconnected)
On login, a client will request all the data it will have access to
At intervals, it will request a list of changes to the data it has access to so it can reconcile the client data locally (and invisibly)
At intervals, or when changes occur (configurable), it will send a batch of all changes the client has made to the server
Please let me know if there are redux libraries that handle all these requirements. Also, feel free to comment if some of the requirements feel like an overengineering or not best practice.
Thanks in advance!

How to create an online-offline application using servicestack

I'm trying to figure out how to create an offline / online approch to use within a huge application.
Right now, each part of the application has its own model and datalayer, who directly read / write data from / to SQL. My boss is asking me to create a kind of buffer that, in case of connectivity failure, might be used to store data until the connection to SQL return active.
What I'm trying to create is something like this: move all datalayers into a servicestack service. Each "GET" method should query the database and store the result into a cache to be reused once the connection to SQL is not available. Each "POST" and "PUT" method must execute their actions or store the request into a cache if the connection fail. this cache must be cleared once the connection to SQL is restored.
How can I achieve this? Mine is a WPF application running on Windows 10.
Best regards
Enrico
Maintaining caches on the server is not going to help create an offline Application given the client wouldn't have access to the server in order to retrieve those caches. What you'd need instead is to maintain state on the client so in the event that network access is lost the client is loading from its own local caches.
Architecturally this is easiest achieved with a Web App using a Single Page App framework like Vue (+ Vuex) or React (+ Redux or MobX). The ServiceStack TechStacks and Gistlyn Apps are good (well documented) examples of this where they store client state in a Vuex store (for TechStacks created in Vue) or Redux Store (for Gistlyn created in React), or the Old TechStacks (created with AngularJS).
For good examples of this checkout Gistlyn's snapshots feature where the entire client state can be restored from a single serialized JSON object or approach used the Real Time Network Traveler example where an initial client state and delta's can be serialized across the network to enable real-time remote control of multiple connected clients.
They weren't developed with offline in mind, but their architecture naturally leads to being offline capable, courtesy of each page being first loaded from its local store then it fires off a Request to update its local cache which thanks to the reactivity of JS SPA fx's, the page is automatically updated with the latest version of the server.
Messaging APIs
HTTP has synchronous tight coupling which isn't ideal for offline communication, what you want instead is to design your write APIs so they're One Way/Asynchronous so you can implement a message queue on the client which queues up Request DTOs and sends them reliably to the server by resending them (using an exponential backoff) until the succeed without error. Then for cases where the client needs to be notified that their request has been processed they can either be done via Server Events or via the client long-polling the server checking to see if their request has been processed.

Chat app: What to do on successful re-connection to the WebSocket server?

My friend and I are currently building a web-based chat app with WebSocket. I'm in charge of client side (React + Redux). Golang is used for the server side (I don't know whether this is a good combination, but I do this just for fun).
Basically my problem is that I don't know what to do after the successful re-connection to the WebSocket server.
More concretely:
The client side tries to reconnect to the server when the connection is lost. My questions are
When the re-connection is successful, what should I do with the data that were supposed to be sent to the server, but actually weren't sent because of the lost connection? Is it better to have something like a buffer to store all the data that are not yet transmitted to the server?
Currently, a React component do the initial fetch of all the necessary data ( rooms, friends, chat history, etc.) on componentDidMount. For the app to be in sync with the server on successful re-connection, the app should perform actions similar to the initial fetch. But calling componentDidMount deliberately does not seem to be a good idea, because it is not supposed to be called in this way. Is it good to perform initial fetching in componentDidMount in the first place?
Since this is is a general question, I will answer in general terms:
You need some kind of buffer between the application and the unreliable stream. Since you're reactive, you can implement this using an observable. The service that is responsible for the actual communication over WebSocket will subscribe to this feed.
Separate the initialization of the component from initialization of the data. If you're communicating over WebSocket, you can reinitialize data every time the socket connects.
Go is certainly a good choice for the chat server because of the way it handles concurrency. The other common option for chat servers is Erlang. React is a matter of personal preference.
You probably don't want to buffer it all. You just want to buffer the messages but not, for instance, typing indicators because they make no sense if not sent immediately. Something as simple as an array with push() and shift() would do.
Move data fetching to a separate function, then call it both from componentDidMount and from the callback or whatever place where you reconnect.
Using both HTTP and websocket in one app is a matter of design. It does seem to complicate things though.

Resources