Open stefnotch opened 11 hours ago
Thanks for the repro, I noticed this or a similar bug last week but had trouble tracking it down. This is a nice minimal example.
Ah you know what, this is actually just the opposite of #3158 which you opened a while ago. Now, rather than deadlocking, having a ReadLock on a memo while it needs to be updated is failing silently.
Using .get()
instead of .read()
fixes the issue.
I am not sure that it is possible to refactor the way memos are structured such that the value and the reactive machinery are separate from one another, because whether a memo needs to update or not depends on its value. So taking a read lock on a memo, and holding that during other reactive operations, is quite tricky.
Any suggestions? Perhaps the answer is just a better answer to errors here, like a console warning instead of either panicking or failing silently?
An error or a warning would be a very welcome improvement indeed. 👍
As for what I'm doing:
I'm using memos with objects that cannot be cloned. For example, GPU shader code is in a signal, and a wgpu::ShaderModule
is in a memo that is derived from the signal.
With the ReadGuard
API I can get a reference to such an object.
In my case, I can also rework my code to use .with(|value| { do something with the value })
, it's just a lot of extra nested code. Alternatively, I could wrap everything in an Arc
, so that the objects are clone-able.
So there's a part of me that very much hopes for a world where the .read()
API almost always works.
Another tidbit worth mentioning: I have quite a lot of memos that always recompute their value when their inputs change. And they never bother comparing the new value with the old value, because they cannot be the same.
For example
Memo::new_with_compare(move |_| createShaderModule(sourceCode.get()), |_, _| true);
And they never bother comparing the new value with the old value, because they cannot be the same. For example
Memo::new_with_compare(move |_| createShaderModule(sourceCode.get()), |_, _| true);
That's fine, this is just not a memo and should be implemented differently. In fact, because of the trait-based approach in reactive_graph
I'm pretty sure it's possible to create your own primitive, in userland, that does not have the same limitations you're seeing with a memo.
On the other hand, I'm not sure what purpose a memo is serving here? If the memos are defined such that they are never the same value, it's a bunch of reactive-graph overhead for no real reason, as far as I can tell.
I used a memo, because it seemed like the most straightforward way of doing "[...] will only run once per change, no matter how many times you access its value.", while also having laziness.
I suppose I could write my own primitive, although I'm not entirely sure where to start.
Describe the bug I have set up a reactive graph with "source => memo 1 => memo 2" and "memo1, memo2 => effect". When I change the source, then the first memo gets recomputed, the effect gets updated, but the second memo stays the same.
Leptos Dependencies
To Reproduce Steps to reproduce the behavior:
Expected behavior It should have printed
Additional context
I also have a demo project that can run in a browser environment leptos-testos.zip
The demo project can also be run in a browser environment by doing
and then serving
index.html
with a HTTP server and opening it in a browser. I originally thought that it was a wasm-bindgen-futures specific bug, but it turned out that I just didn't manage to properly reproduce it on desktop.