This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # beginners (29)
- # boot (17)
- # calva (1)
- # cider (31)
- # cljs-dev (3)
- # clojure (169)
- # clojure-europe (1)
- # clojure-france (1)
- # clojure-russia (40)
- # clojure-serbia (3)
- # clojure-uk (42)
- # clojurescript (19)
- # clr (3)
- # core-async (7)
- # core-typed (3)
- # cursive (43)
- # datascript (4)
- # datomic (2)
- # dirac (4)
- # emacs (2)
- # fulcro (85)
- # funcool (1)
- # nrepl (5)
- # off-topic (14)
- # shadow-cljs (28)
- # spacemacs (5)
- # tools-deps (2)
@mdhaney Wow,Thank you for your reply.I can’t figure out why my :started-callback can’t load things from the server.How do you debug the client server communication problem?Thanks.😊
console.error: "[18.362s] [fulcro.client.network] Transit decode failed! SyntaxError:Unexpected token u in JSON at position 0"
@eric.shao what are you sending back and forth? That is a transit failure. Perhaps you sent some data that transit can encode in JVM, but not decode in cljs?
@tony.kay I think it is in cljs,not even touch the server. 1. The df/load code in RN client side is identical to the Web client side .And the web’s reaction is right. 2: The problem is in df/load(there is a console.log) but before the http request was even sent. Because in the react native debug console’s network tab there is not a new XHR and the console.log in server’s defquery is not invoked. I’ll try again from scratch.
1. Still the same Transit decode error.
2. The :ident begin to show problem
[ 3.697s] [fulcro.client.primitives] component main.state-machine-ws.ui.components/PersonList’s ident ([:person-list/by-id nil]) has a
nil second element. This warning can be safely ignored if that is intended.
[ 3.703s] [fulcro.client.primitives] component main.state-machine-ws.ui.components/Person’s ident ([:person/by-id nil]) has a
nil second element. This warning can be safely ignored if that is intended.
3. Without REPL and FulcroInspector it’s hard to http://program.It reminds me how much work tony has put to make our work easy with FulcroWeb. Thank you Mr. tony.kay.
4. Mr @mdhaney , please share your experience in code and articles.😊
Hi! I have a “library” for my Fulcro project in the
main directory, i.e.
src/main/my_project/core/lib.cljc. I would like to test it using devcards, so I created a file
src/cards/my_project/core/lib.cljs (mirroring the
main tree). I thought I would be apple to access methods define in my
lib.cljc file but it looks like it’s not getting compiled as part of
shadow-cljs watch cards. How can I remedy this?
I solved the problem by renaming my cards namespace to
lib_cards, after which I could import the
core/lib.cljc namespace and take it from there. I would rather have both share the same namespace though, so my question still stands 🙂
@eric.shao your problem might be shadow-cljs. When I started this project and looked into shadow-cljs, they were in limbo with RN support (there were some older attempts that kinda worked, but then broke with newer releases). The Expo lein template worked out of the box, but it doesn’t support Fulcro and only supported Expo 26, which is about 10 months old now. What I did was start with the Expo template and Om.next, then swapped out Fulcro for Om and upgraded the Expo version to 30, which is the last release on RN 55 (versions 56 and 57 had a lot of tooling changes, and last I checked re-natal wasn’t even supporting them yet). This has worked quite well. I get a working REPL, which has proved invaluable. Fulcro inspect isn’t working - it’s not detecting the Fulcro app when I run the app remotely on Chrome. It seems to me this might be fixable, but I haven’t had the cycles to dig into it. To avoid the externs issue, I’m using cljs-oops and so far that has worked well. I’ll pull out the core client code and upload a project tonight. Converting the Expo template to use Fulcro and upgrade Expo was pretty straightforward, but IIRC there were a couple of gotchas during the process.
Fulcro 2.7.0 released. This includes a breaking change in websockets (the API for sente changed due to a security hole (which we had a workaround for)). It also fixes a bug in SSR state encode/decode. Thanks @lennart.buit.
@tony.kay I am about to start a new fulcro project. Would you recommend the websocket transport or the HTTP transport? My only real requirement is that order of mutations is preserved (i.e. the transport doesnt submit a mutation to the server until it has received a confirmation by the server that the previous mutation has been processed)
@hmaurer both are fine. If you submit a tx as a unit to a single remote, then the sequence of calls in that tx will be preserved, but it will be transmitted all at once. So, the behavior on the server is up to you. If the mutations are queued in separate event invocations, then Fulcro, by default, serializes requests
[(g)] is possibly different in processing from
[(f) (g)], but is up to your implementation on the server. There are 2 possible scenarios for the 1st.
If 2 txes are submitted on the same user event, then they are combined, and are equivalent to the second form
Okay, so both would be fine? My use-case would be the later (separate mutations). Roughly speaking I am building an exercise application, where the state of exercises are dictated by a sequence of events. The user (student) does an action on the frontend which moidfies the state of the exercise. I want to apply it optimistically on the frontend (to show new state without lag) and also transmit the event to the backend to persist the student’s current exercise state
The reason why it needs serialisation is that a student might perform multiple actions quickly in a row, in which case we would want the server state to be the same as the client’s state
Great 🙂 And what is the default behaviour in case of failure on the server side? (also, is the default behaviour to apply the mutation optimistically on the frontend?)
Yep, I was basically asking: if
A -> B -> C are applied optimistically on the frontend (where A, B, C are mutations), and the server queue fails on
B, what happens?
Start by reading the stuff on ptransact! in the book, then look at the pessimistic mutation docs in incubator
I’ll definitely read that; in my case I don’t want to hard fail if a mutation fails. The idea is to “sync” a client state (exercise state) with a server state. So I want to let the student keep going in the exercise, and perhaps if syncing really fails (i.e. 3 retries fail) then give a warning that the connexion might be broken and that his progress will be lost
or syncing might fail because the auth token expired, in which case I would just want to refresh it and retry
Hm…the docs on incubator are a little weird on that. You can use normal Fulcro
ptransact! with those now…it mentions transact functions in incubator, which are not necessary.
So, you might even consider implementing retry at the network layer. The built-in Fulcro remote isn’t that complicated (use the source), and that kind of recovery would probably be best handled at that layer.
Websocket support has a basic version of that (auto-retry), BUT it requires your mutations be idempotent (as your own implementation would need to as well, since you can’t know on a failure what the server saw)
does that suggestion apply regardless of whether the transport is http or websocket? or is one easier than the other ?
I guess I can make mutations idempotent by tagging them with an ID and check that on the backend
Auto-retry could be added to the built in normal one as well, but most of my projects use websockets, so it got the attn on that.
so I guess using websocket is also a better idea if I want to get the most out of you, should any issue arise 😛
not necessarily 🙂 The code works “well enough” for me that I’ve not had to look at the network layer in some time. I wouldn’t say I’m any better at dealing with issues on either.
I looked further at the docs. It think the incubator stuff is actually all ok…the comment on “composition” https://github.com/fulcrologic/fulcro-incubator#composition is what I was trying to get at/remember.
But I think they might mislead you slightly unless you know this: Separate invocations will not have a blocking behavior (e.g. 2 calls to ptransact will never be combined of block each other)…so, it requires a bit more care…but auto-retry at the network layer sounds like a better call. YOu can also get network status notifications from websockets (though they are sometimes delayed a lot by browser implementation).
(pm/ptransact! this [(f) (g)]) may delay the invocation of
f completes full stack…but if the user submits a new tx
(h), then that one won’t* necessarily be blocked by the completion of the (yet incomplete)
g. You could see f, h, g. The order that is guaranteed is that
g comes after
Sorry, just to clarify:
(prim/ptransact! this '[(a) (b)]) will run (a) and (b) serially, but you said that mutations are also queued by remote, right? and serially applied
(pm/ptransact! this [(f)]) (pm/ptransact! this [(g)])
(pm/ptransact! this [(h)])
(pm/ptransact! this [(f) (g)]) it would optimistically run
f, wait for completion, and if successful optimistically run
g and wait for comlpetion?
Thanks for pointing that out; it would definitely have confused me if I stumbled on it
The main point of ptransact is to be able to hold off on optimistic updates until a remote has completed.