mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 12:43:08 +00:00
better diagnostics for use_shared_state
This commit is contained in:
parent
970c43702e
commit
469a7ac0af
3 changed files with 75 additions and 7 deletions
|
@ -76,6 +76,7 @@ futures-util = { version = "0.3", default-features = false }
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
wasm-bindgen = "0.2.87"
|
wasm-bindgen = "0.2.87"
|
||||||
html_parser = "0.7.0"
|
html_parser = "0.7.0"
|
||||||
|
thiserror = "1.0.30"
|
||||||
|
|
||||||
# This is a "virtual package"
|
# This is a "virtual package"
|
||||||
# It is not meant to be published, but is used so "cargo run --example XYZ" works properly
|
# It is not meant to be published, but is used so "cargo run --example XYZ" works properly
|
||||||
|
@ -112,9 +113,9 @@ rand = { version = "0.8.4", features = ["small_rng"] }
|
||||||
tokio = { version = "1.16.1", features = ["full"] }
|
tokio = { version = "1.16.1", features = ["full"] }
|
||||||
reqwest = { version = "0.11.9", features = ["json"] }
|
reqwest = { version = "0.11.9", features = ["json"] }
|
||||||
fern = { version = "0.6.0", features = ["colored"] }
|
fern = { version = "0.6.0", features = ["colored"] }
|
||||||
thiserror = "1.0.30"
|
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
simple_logger = "4.0.0"
|
simple_logger = "4.0.0"
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
|
@ -14,6 +14,7 @@ keywords = ["dom", "ui", "gui", "react"]
|
||||||
dioxus-core = { workspace = true }
|
dioxus-core = { workspace = true }
|
||||||
futures-channel = { workspace = true }
|
futures-channel = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -121,30 +121,96 @@ pub struct UseSharedState<T> {
|
||||||
pub(crate) inner: Rc<RefCell<ProvidedStateInner<T>>>,
|
pub(crate) inner: Rc<RefCell<ProvidedStateInner<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum UseSharedStateError {
|
||||||
|
#[error("{type_name} is already borrowed, so it cannot be borrowed mutably.")]
|
||||||
|
AlreadyBorrowed {
|
||||||
|
source: core::cell::BorrowMutError,
|
||||||
|
type_name: &'static str,
|
||||||
|
},
|
||||||
|
#[error("{type_name} is already borrowed mutably, so it cannot be borrowed anymore.")]
|
||||||
|
AlreadyBorrowedMutably {
|
||||||
|
source: core::cell::BorrowError,
|
||||||
|
type_name: &'static str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type UseSharedStateResult<T> = Result<T, UseSharedStateError>;
|
||||||
|
|
||||||
impl<T> UseSharedState<T> {
|
impl<T> UseSharedState<T> {
|
||||||
/// Notify all consumers of the state that it has changed. (This is called automatically when you call "write")
|
/// Notify all consumers of the state that it has changed. (This is called automatically when you call "write")
|
||||||
pub fn notify_consumers(&self) {
|
pub fn notify_consumers(&self) {
|
||||||
self.inner.borrow_mut().notify_consumers();
|
self.inner.borrow_mut().notify_consumers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try reading the shared state
|
||||||
|
pub fn try_read(&self) -> UseSharedStateResult<Ref<'_, T>> {
|
||||||
|
self.inner
|
||||||
|
.try_borrow()
|
||||||
|
.map_err(|source| UseSharedStateError::AlreadyBorrowedMutably {
|
||||||
|
source,
|
||||||
|
type_name: std::any::type_name::<Self>(),
|
||||||
|
})
|
||||||
|
.map(|value| Ref::map(value, |inner| &inner.value))
|
||||||
|
}
|
||||||
/// Read the shared value
|
/// Read the shared value
|
||||||
pub fn read(&self) -> Ref<'_, T> {
|
pub fn read(&self) -> Ref<'_, T> {
|
||||||
Ref::map(self.inner.borrow(), |inner| &inner.value)
|
match self.try_read() {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(message) => panic!(
|
||||||
|
"Reading the shared state failed: {}\n({:?})",
|
||||||
|
message, message
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try writing the shared state
|
||||||
|
pub fn try_write(&self) -> UseSharedStateResult<RefMut<'_, T>> {
|
||||||
|
self.inner
|
||||||
|
.try_borrow_mut()
|
||||||
|
.map_err(|source| UseSharedStateError::AlreadyBorrowed {
|
||||||
|
source,
|
||||||
|
type_name: std::any::type_name::<Self>(),
|
||||||
|
})
|
||||||
|
.map(|mut value| {
|
||||||
|
value.notify_consumers();
|
||||||
|
RefMut::map(value, |inner| &mut inner.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
/// Calling "write" will force the component to re-render
|
/// Calling "write" will force the component to re-render
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
// TODO: We prevent unncessary notifications only in the hook, but we should figure out some more global lock
|
// TODO: We prevent unncessary notifications only in the hook, but we should figure out some more global lock
|
||||||
pub fn write(&self) -> RefMut<'_, T> {
|
pub fn write(&self) -> RefMut<'_, T> {
|
||||||
let mut value = self.inner.borrow_mut();
|
match self.try_write() {
|
||||||
value.notify_consumers();
|
Ok(value) => value,
|
||||||
RefMut::map(value, |inner| &mut inner.value)
|
Err(message) => panic!(
|
||||||
|
"Writing to shared state failed: {}\n({:?})",
|
||||||
|
message, message
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows the ability to write the value without forcing a re-render
|
/// Tries writing the value without forcing a re-render
|
||||||
|
pub fn try_write_silent(&self) -> UseSharedStateResult<RefMut<'_, T>> {
|
||||||
|
self.inner
|
||||||
|
.try_borrow_mut()
|
||||||
|
.map_err(|source| UseSharedStateError::AlreadyBorrowed {
|
||||||
|
source,
|
||||||
|
type_name: std::any::type_name::<Self>(),
|
||||||
|
})
|
||||||
|
.map(|value| RefMut::map(value, |inner| &mut inner.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes the value without forcing a re-render
|
||||||
pub fn write_silent(&self) -> RefMut<'_, T> {
|
pub fn write_silent(&self) -> RefMut<'_, T> {
|
||||||
RefMut::map(self.inner.borrow_mut(), |inner| &mut inner.value)
|
match self.try_write_silent() {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(message) => panic!(
|
||||||
|
"Writing to shared state silently failed: {}\n({:?})",
|
||||||
|
message, message
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue