-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UseStateHandle
can become stale
#2112
Comments
@mc1098 I would love to attempt to solve this but I'm not sure how to reproduce this. Could you provide a small example that i could use as a base? |
@voidpumpkin small and contrived example :) Funny enough, I actually think someone might have come across this before because in the docs for Custom Hooks the example uses a |
@mc1098 so then perhaps this issue can be closed? |
@voidpumpkin Nope 🙃. Using the I'd like to keep this issue open to explore how we could change |
I guess we need to add a separate pub struct UseCellHandle<T> {
value: Rc<RefCell<Rc<T>>>,
setter: Rc<dyn Fn(T)>,
}
impl UseCellHandle<T> {
fn set(&self, value: T) {
(self.setter)(value)
}
fn get(&self) -> Rc<T> {
(*self.value.borrow()).clone()
}
// Maybe also get_owned() and take() ?
}
impl UseCellHandle<T>
where
T: PartialEq
{
fn set_if_neq(&self, value: T) {
if (**self.value.borrow()) != value {
self.set(value)
}
}
} This hook should behave like I guess it's better to make Also I am not sure if we should rename In addition, I have read the implementation of
However, Yew's I guess the proper way to solve this is:
And reimplement the following hooks with
Make a distinction between
In addition, add documentation to discourage manual checking when setting values of Optionally, add a I am not very decided on the naming, the ones I can come up with: I guess this implementation should address:
|
@mc1098 I have file a two-part PR that intends to solve this issue. Could you please take a look and let me know the thoughts? |
It was mentioned in #2109 about how the
UseStateHandle
can contain stale data - this is the case because inuse_state
we replace theRc<T>
on each set which means anyRc
s that handles are holding are now stale. The handle keeps theRc
in scope so it will always be valid but this isn't what most people would expect.The reason this goes somewhat unnoticed is that we often re-create
Callback
s so will move in the updatedUseStateHandle
so that the value is valid, however, when you pass it to something like anAgent
or the router listener callback then it is a singleCallback
that never gets updated and whatever the state was when that handle was passed in is what it will remain to be.So solving this issue is actually bit difficult without causing ergonomic pain (unless I'm missing something, and I hope I am). If we used a
Rc<RefCell<T>>
withuse_state
and then encapsulated that in theUseStateHandle
then our state could remain in sync which is good.We would have to make sure that users of handle could not mutate the state other than the
set
fns.UseStateHandle
could no longer implDeref
and would have to have a borrow function likeRefCell
so we could enforce the borrow lifetime constraints for exclusive mutability when we actually run the setter. I think if we uphold the lifetime constraints we can guarantee that we won't panic when trying to get a mutable borrow of state.We could dip our toes into some unsafe 👀 and use
UnsafeCell
in order to still implDeref
and avoid theRefCell
runtime borrow checks - I haven't thought too much on the safety argument but I think it would be safe to do this as we'd only give out references toT
with a lifetime that is bound to theUseStateHandle
so would prevent someone from deref -ing state then passing it to aCallback
as they all require'static
lifetimes. We can then happily mutably borrow the state in the setter because this is within the scheduler so we can't have outstanding borrows to state because we require'static
lifetimes to store anything.I'd love to hear from others regarding the above and whether I missed something or if there is a better way to it all :) We can either try and resolve it or document it - but the latter would be a shame because I think this behaviour will catch people out.
The text was updated successfully, but these errors were encountered: