reactjscachingscala.jsscalajs-react

React Simple Global Entity Cache instead of Flux/React/etc


I am writing a little "fun" Scala/Scala.js project.

On my server I have Entities which are referenced by uuid-s (inside Ref-s).

For the sake of "fun", I don't want to use flux/redux architecture but still use React on the client (with ScalaJS-React).

What I am trying to do instead is to have a simple cache, for example:

The way I would like to implement this is the following :

QUESTIONS:

1) Am I doing something really wrong if I am doing the state handling this way ?

2) Is there an already existing solution for this ?

I looked around but everything was FLUX/REDUX etc... along these lines... - which I want to AVOID for the sake of :


Solution

  • Consider what issues you need to address to build a rich dynamic web UI, and what libraries / layers typically handle those issues for you.

    1. DOM Events (clicks etc.) need to trigger changes in State

    This is relatively easy. DOM nodes expose callback-based listener API that is straightforward to adapt to any architecture.

    2. Changes in State need to trigger updates to DOM nodes

    This is trickier because it needs to be done efficiently and in a maintainable manner. You don't want to re-render your whole component from scratch whenever its state changes, and you don't want to write tons of jquery-style spaghetti code to manually update the DOM as that would be too error prone even if efficient at runtime.

    This problem is mainly why libraries like React exist, they abstract this away behind virtual DOM. But you can also abstract this away without virtual DOM, like my own Laminar library does.

    Forgoing a library solution to this problem is only workable for simpler apps.

    3. Components should be able to read / write Global State

    This is the part that flux / redux solve. Specifically, these are issues #1 and #2 all over again, except as applied to global state as opposed to component state.

    4. Caching

    Caching is hard because cache needs to be invalidated at some point, on top of everything else above.

    Flux / redux do not help with this at all. One of the libraries that does help is Relay, which works much like your proposed solution, except way more elaborate, and on top of React and GraphQL. Reading its documentation will help you with your problem. You can definitely implement a small subset of relay's functionality in plain Scala.js if you don't need the whole React / GraphQL baggage, but you need to know the prior art.

    5. Serialization and type safety

    This is the only issue on this list that relates to Scala.js as opposed to Javascript and SPAs in general.

    Scala objects need to be serialized to travel over the network. Into JSON, protobufs, or whatever else, but you need a system for this that will not involve error-prone manual work. There are many Scala.js libraries that address this issue such as upickle, Autowire, endpoints, sloth, etc. Key words: "Scala JSON library", or "Scala type-safe RPC", depending on what kind of solution you want.


    I hope these principles suffice as an answer. When you understand these issues, it should be obvious whether your solution will work for a given use case or not. As it is, you didn't describe how your solution addresses issues 2, 4, and 5. You can use some of the libraries I mentioned or implement your own solutions with similar ideas / algorithms.


    On a minor technical note, consider implementing an async, Future-based API for your cache layer, so that it returns Future[Entity] instead of Loading | Entity.