Last active
August 7, 2023 04:40
-
-
Save joshcho/3c0ec077143dd15231b983042d4c2dc9 to your computer and use it in GitHub Desktop.
A simple example of optimistic bidirectional updates in Electric
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns relay.example | |
#?(:cljs (:require-macros [app.push :refer [make-relay]])) | |
(:require | |
#?(:clj [datascript.core :as d]) | |
[hyperfiddle.electric :as e])) | |
#?(:clj | |
(defmacro make-relay | |
"Make `ref` into a client-side relay atom. The relay atom does bidirectional updates with the server, | |
indicated by server-value (the flow) and server-effect (the client to server update). The server to | |
client update is a `reset!`." | |
[ref server-value server-effect] | |
`(let [!client-value ~ref] | |
(reset! !client-value (e/snapshot (e/server ~server-value))) | |
;; sync from client to server | |
(let [client-value (e/watch !client-value)] | |
(when (boolean? client-value) | |
(e/server (~server-effect client-value)))) | |
;; sync from server to client | |
(let [server-value (e/server ~server-value)] | |
(when (boolean? server-value) | |
(reset! !client-value server-value)))))) | |
;; example | |
(let [task (e/server | |
(:task/name (d/entity db task-id))) | |
!toggled (atom nil) ; must be set to nil, is overwritten in make-relay | |
;; could not figure out a way to do make-relay that returns an atom to be used directly as !toggled | |
] | |
(make-relay !toggled | |
(:task/toggled (d/entity db task-id)) | |
(fn [v] | |
(d/transact! | |
!conn [{:db/id task-id :task/toggled v}]))) | |
;; now client-side reset! and swap! on !toggled propagates to the server data, | |
;; which is (:task/toggled (d/entity db task-id)), and changes to server data | |
;; caused by other clients propagate to !toggled. | |
;; potential races not handled | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment