Saving client state in reagent / Clojurescript

I am not sure how to do this:

I have a web application that I am writing that implements the basic CRUD functions for several Project objects. Thus, the user can create his own set of projects.

I wrote a REST API for adding / removing / listing projects, and I wrote a Reagent client interface. Customer projects are stored in the atom reagent (ratom), as expected.

Here it becomes interesting.

In all the tutorials I've seen, it shows you how to update ratom, and your GUI will update automatically. I have it, it works.

What I am doing now is at the time of updating the status of the client, I make my REST POST call to update the status of the server in the database.

But this is not so. I now save state in two places: on the client and on the server, and both can be different.

If I implemented this as a regular old web page, the server would send the page back to the client with the latest database state. But the state already exists on the client in ratom, and I don't know how to synchronize it.

Should I make another server call (GET request) after successfully completing the initial POST? This can replace the contents of ramat. Then I make two requests that seem wasteful.

Or it is best to use something like chord or sente to control client state asynchronously. This would be better, as it would mean that changes from other users would be instantly updated on the client side. But I don’t see any textbooks showing a reaction to any of them, so maybe I'm wrong.

So the question is, how should the reaction be combined with REST?

thanks

+7
clojure reactjs clojurescript reagent
source share
3 answers

I agree with @myguidingstar that your problem is more likely with client-server synchronization than with clojure or reagent. You could have a similar problem with, say, GWT (was there, ...)

Should I make another server call (GET request) after successfully completing the initial POST? This can replace the contents of ramat. Then I make two requests that seem wasteful.

You seem to miss that POST requests can also trigger responses from the server.

The big question is, why do you need the state of the database on the client? Do you have requirements that make you minimize the number of GET requests to retrieve data from the server? Or do you have client-side business logic (ClojureScript / reagent) that just doesn't require server interaction? You also need to consider the same problem: is it good if your client status is not updated after some time or you may encounter problems of consistency, because "something else" changes the data on the server behind your client back?

Finally, you say that you

.. don’t know how to synchronize it with me.

What are your concerns? Why not just update the application state ( swap! app-state update-in ...) App swap! app-state update-in ...) after you retrieved the data from the server, as described in the reagent-tutorial ?

+3
source share

This is a big question about client-server synchronization, which most web applications encounter.

There is a Tonsky library for the problem itself:

https://github.com/tonsky/datascript

Read his blog post and datascript-chat example to understand the design. It will take a lot to learn, but I'm afraid this is the only way that is not "insensitive."

+1
source share

As others have noted, this is a common design problem for any client-server application where there can be more than one client. I think the key is to carefully examine what state you need to maintain in your client. Questions such as, "Does your client need up-to-date information about the status of the server or the remote database, or just need the latest information about the actions the client takes? For example, do you need to know what the remote database table is after updating, or you just need to know Was your update successful or not?

Another thing I've seen that can lead to the wrong way is too early. To improve efficiency, the design sometimes tries to include too many states in the local client, believing that this will reduce the number of calls on the remote server and make the application more responsive. However, often you may encounter an overly complex implementation, which is difficult to cope with many local management costs, often including a lot of information that is used or used only in limited or rarely used parts of the client interface. The next thing you know, your application is losing effectiveness because it works to maintain state synchronization, which is not needed.

The problem here is due to our tendency to think about problems in a serialized way. It is natural. However, the problem here is not entirely suitable for this way of thinking. The remote state of the system changes at an unpredictable rate. Even if you adopt an architecture that pushes changes to the client, you will encounter problems associated with developing how often such changes should be pushed, and then how to reflect these changes in the interface, so that the user becomes a consistent and meaningful picture.

My approach, which is just one of many and may not be the most ideal, is to model a web application along the same lines as many database clients (and to some extent even Clojure's own STMs). A state in a client is a snapshot of a remote state at a specific point in time. It may not be accurate or relevant, but it must be consistent. When a client sends changes, it may or may not be successful, depending on what has changed on the server, since I started to enter my change in the client. If he succeeds, he completes completely, and if he fails, he fails completely.

As others have noted, this is not directly related to the reagent. This is a boder design problem. However, this may have an indirect effect. For example, when you update a reagent atom, your reagent contains er will be displayed. The atom knows when it is being updated, but it does not know when the update is updating existing information without change, so you really want to update the atom when it needs to be updated, because something has changed. However, if this happens very often, and your component is really very complex, you probably will not see any real effect, even if you often update updates such as updates.

I would focus on minimizing the state and developing a really simple design, then download the test and develop if there are performance problems and deal with them as they arise.

+1
source share

All Articles