Fork me on GitHub
#fulcro
<
2022-09-21
>
sheluchin10:09:21

I have a report with a custom ro/BodyItem. When I route to it the report for the first time, the rows are correct. If I then go back and select another related report, the rows do not update from the previous visit to. If I go back again and select a third related report, the rows from the second report appear in it. And so it lags behind one like this each time. All the while, the data in the db as well as the props of the BodyItem are correct. I've tried to use the troubleshooting tree to figure it out. The db->tree result looks correct to me. The only errors I'm seeing in the console are:

react_devtools_backend.js:4026 WARN [com.fulcrologic.fulcro.ui-state-machines:691] -  UNEXPECTED EVENT: Did not find a way to handle event :ready! in the current active state: :routed See 

react_devtools_backend.js:4026 WARN [com.fulcrologic.fulcro.ui-state-machines:691] -  UNEXPECTED EVENT: Did not find a way to handle event :event/resume in the current active state: :state/loading See 
UPDATE: it seems to only happen if I have a https://prismjs.com/docs/Prism.html#.highlightAll in :componentDidMount... I notice that :componentDidMount gets called with old (previous) props while :componentDidUpdate recieves the new props. Is this normal or perhaps indicative of some error?

tony.kay17:09:05

That is stock React. Read the react docs.

sheluchin17:09:29

@U0CKQ19AQ I've been reading them but I guess I'm misunderstanding the intersection with RAD reports? I guess you're referring to the part about :componentDidMount only getting called on initial render? I fail to see how it can lead to the data in the UI not being updated and why omitting that library call makes it all work.

tony.kay17:09:06

I’m saying that componentDidMount and componentDidUpdate are REACT things. What you are seeing them do is controlled by React.

tony.kay17:09:31

You should NOT be using them with reports. You should augment/edit the state machine of the RAD report/form if you want to augment the logic.

tony.kay17:09:34

https://book.fulcrologic.com/RAD.html#_augmenting_form_behavior and the procedure for messing with reports is nearly identical, though the machine is different. Use the source of the machines

sheluchin17:09:33

Hmm, they shouldn't be used with reports? I didn't know that. But I did try using ro/load-report to just call the side-effecting function before returning the unmodified uism-env and it didn't seem to do the trick.

tony.kay17:09:01

This level of customization is really at the UISM level, and has nothing to do with RAD per se. Other than you’re modifying a state machine that your report is using.

sheluchin17:09:51

However, I've been trying to use :componentDidMount on the defsc ro/BodyItem, not on the defsc-report. It shouldn't be used there either?

tony.kay17:09:54

React lifecycle hooks should generally be avoided everywhere because it complects React’s rendering with your own side-effects, and coupling the two is a bad idea. This is why RAD uses UISM to control the logic

tony.kay17:09:28

Well, for convenience I can see the desire to do so

tony.kay17:09:01

and on BodyItem elements you’re at least not competing with the top-level logic

tony.kay17:09:00

but I think you’re getting confused by what React gives you in those, and may be running into react keys issues as well (perhaps it isn’t remounting the rows because it thinks they are the same component with just changed data)

sheluchin17:09:02

I mean it's just a single function call that's supposed to decorate a dom element with some syntax highlighting. I did read your advice to Gene in this thread https://clojurians.slack.com/archives/C68M60S4F/p1660066678343479?thread_ts=1660065105.976959&amp;cid=C68M60S4F and since my customization (single fn call) is so simple, I thought it was the right choice.

sheluchin17:09:16

I did try it like this:

ro/report-loaded (fn [uism-env]             
                   (.highlightAll js/Prism) 
                   uism-env)                
instead of using the lifecycle methods.

tony.kay17:09:53

I don’t see why the report-loaded would not work, other than if there was pagination

tony.kay17:09:39

but it seems to me the right thing to do would be to create a react component that renders text with highlighting, and use that to render the value, instead of trying to be side-effect-y on a DOM React controls

sheluchin17:09:29

Well, I mean I don't want to re-invent the wheel to accomplish syntax highlighting when there are mature libraries that do it. Perhaps you mean something else? Is there another means of applying such a post-rendering library or..?

tony.kay17:09:52

I’m saying you should be carefully reviewing React docs for how to do that correctly, and you should isolate that need into a React component that is properly written:

(defsc HighlightedText [this {:keys [text]}]
 {}
 ...proper code that is react compatible...)

tony.kay17:09:26

of course you should a library to do the actual highlighting if you have one.

tony.kay17:09:39

but a low-level js lib that is not React aware will cause you nightmares

tony.kay17:09:55

that’s what you should be integrating with

sheluchin17:09:10

Okay, I understand the direction you're suggesting. I thought I was making such a defsc component through this BodyItem but what you're saying about avoiding the lifecycle methods makes sense.

tony.kay17:09:41

No, BodyItem is generating a React thing. Using a non-react library to modify the DOM it generated will never work right

tony.kay17:09:52

it might “sorta work”, but it will never work right

sheluchin18:09:13

hah that's exactly how it feels in the places it does work

tony.kay18:09:29

no surprise at all

tony.kay18:09:43

you have two libraries trying to control the DOM, that are unaware of each other

tony.kay18:09:48

how is that supposed to work right?

sheluchin18:09:13

I thought one was done its work and the second would do the work it needs.

tony.kay18:09:30

but you have no control over either’s priority or when they might refresh

sheluchin18:09:33

Bad assumption.

tony.kay18:09:34

so it’s just a mess

sheluchin18:09:46

Okay, thanks very much. Sorry if I missed this guidance in the docs 🙏 Back to the editor.

tony.kay18:09:12

no worries. If you want to use low-level js libs with react, you have to be a ninja with low-level react and figure out all the gears

📝 1
tony.kay18:09:20

much easier to look for someone that’s already done that work

sheluchin18:09:51

So always, always, always look for react components that are made using low-level libs, rather than trying to apply the libs directly.

sheluchin18:09:21

Basically, avoid side-effecty js calls in Fulcro.

tony.kay18:09:50

Fulcro has nothing to do with your problem/task. You’re doing low-level DOM stuff. React is always in control of that. Fulcro is a data management library that allows you to render that state with React. the rendering is ALL react.

tony.kay18:09:59

Just because you are typing cljs code while using Fulcro does not mean Fulcro has much to do with it 🙂

sheluchin18:09:05

I actually never really learned React directly, most of my exposure is through Fulcro. I should probably commit a few weeks study time to level up.

tony.kay18:09:05

Yeah, it’s nice to be able to ignore it when possible, and for simple UI stuff you can. But when you get to these kinds of low-level DOM things, it’s going to be ALL react and no Fulcro (other than knowing how to get your react stuff into cljs and Fulcro’s syntax correctly)

Eric Dvorsak13:09:07

In the durable-mutation doc, there's mention of MutationStore but I can't find any protocol by that name https://cljdoc.org/d/com.fulcrologic/fulcro/3.4.4/api/com.fulcrologic.fulcro.offline.durable-mutations

tony.kay17:09:22

offline/DurableEDNStore…sorry for the naming mixup

tony.kay17:09:02

the protocol is just general storage of EDN things in arbitrary place. Mutations just happen to be encoded as EDN

zhuxun219:09:02

I don't quite get this code block.

Jakub Holý (HolyJak)18:09:45

No. Scroll little up to the image. The code is incomplete. There should be a Settings comp contain the S. Router. I think the complete code is elsewhere in the book.