add memo
This commit is contained in:
1 parent
717c09c4a3
commit
7f2049b647
6 files changed
+137
-4
No files matched your search
@@ -1,3 +1,6 @@
|
||||
use core::{self, fmt::Debug};
|
||||
use std::fmt::{self, Formatter};
|
||||
|
||||
use dioxus_core::prelude::*;
|
||||
|
||||
use crate::CopyValue;
|
||||
@@ -19,7 +22,13 @@ pub(crate) fn get_effect_stack() -> EffectStack {
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct Effect {
|
||||
callback: CopyValue<Box<dyn FnMut()>>,
|
||||
pub(crate) callback: CopyValue<Box<dyn FnMut()>>,
|
||||
}
|
||||
|
||||
impl Debug for Effect {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_fmt(format_args!("{:?}", self.callback.value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Effect {
|
||||
|
||||
@@ -8,8 +8,9 @@ mod rt;
|
||||
pub use rt::*;
|
||||
mod effect;
|
||||
pub use effect::*;
|
||||
#[macro_use]
|
||||
mod impls;
|
||||
mod memo;
|
||||
pub use memo::*;
|
||||
|
||||
use dioxus_core::{
|
||||
prelude::{current_scope_id, has_context, provide_context, schedule_update_any},
|
||||
@@ -55,7 +56,7 @@ struct SignalData<T> {
|
||||
}
|
||||
|
||||
pub struct Signal<T: 'static> {
|
||||
inner: CopyValue<SignalData<T>>,
|
||||
pub(crate) inner: CopyValue<SignalData<T>>,
|
||||
}
|
||||
|
||||
impl<T: 'static> Signal<T> {
|
||||
@@ -115,6 +116,11 @@ impl<T: 'static> Signal<T> {
|
||||
let subscribers =
|
||||
{ std::mem::take(&mut *self.inner.read().effect_subscribers.borrow_mut()) };
|
||||
for effect in subscribers {
|
||||
log::trace!(
|
||||
"Write on {:?} triggered effect {:?}",
|
||||
self.inner.value,
|
||||
effect
|
||||
);
|
||||
effect.try_run();
|
||||
}
|
||||
|
||||
@@ -122,7 +128,7 @@ impl<T: 'static> Signal<T> {
|
||||
RefMut::map(inner, |v| &mut v.value)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, value: T) {
|
||||
pub fn set(&self, value: T) {
|
||||
*self.write() = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
use dioxus_core::prelude::*;
|
||||
|
||||
use crate::{get_effect_stack, CopyValue, Effect, Signal, SignalData};
|
||||
|
||||
pub fn use_memo<R: PartialEq>(cx: &ScopeState, f: impl FnMut() -> R + 'static) -> Signal<R> {
|
||||
*cx.use_hook(|| memo(f))
|
||||
}
|
||||
|
||||
pub fn memo<R: PartialEq>(mut f: impl FnMut() -> R + 'static) -> Signal<R> {
|
||||
let state = Signal::<R> {
|
||||
inner: CopyValue::invalid(),
|
||||
};
|
||||
let effect = Effect {
|
||||
callback: CopyValue::invalid(),
|
||||
};
|
||||
|
||||
{
|
||||
get_effect_stack().effects.write().push(effect);
|
||||
}
|
||||
state.inner.value.set(SignalData {
|
||||
subscribers: Default::default(),
|
||||
effect_subscribers: Default::default(),
|
||||
update_any: schedule_update_any().expect("in a virtual dom"),
|
||||
value: f(),
|
||||
});
|
||||
{
|
||||
get_effect_stack().effects.write().pop();
|
||||
}
|
||||
|
||||
effect.callback.value.set(Box::new(move || {
|
||||
let value = f();
|
||||
let changed = {
|
||||
let state = state.read();
|
||||
value != *state
|
||||
};
|
||||
if changed {
|
||||
state.set(value)
|
||||
}
|
||||
}));
|
||||
|
||||
state
|
||||
}
|
||||
@@ -64,6 +64,15 @@ impl<T: 'static> CopyValue<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn invalid() -> Self {
|
||||
let owner = current_owner();
|
||||
|
||||
Self {
|
||||
value: owner.invalid(),
|
||||
origin_scope: current_scope_id().expect("in a virtual dom"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn origin_scope(&self) -> ScopeId {
|
||||
self.origin_scope
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user