Compare commits

...

2 Commits

Author SHA1 Message Date
Greg Johnston
ed405c1f27 Fixes hydration errors for elements following a \<Suspense/\> 2023-02-16 19:22:05 -05:00
Greg Johnston
3e47a4b566 create_many_signals 2023-02-16 07:32:42 -05:00
3 changed files with 97 additions and 2 deletions

View File

@@ -87,6 +87,7 @@ where
} else {
// run the child; we'll probably throw this away, but it will register resource reads
let child = orig_child(cx).into_view(cx);
let after_original_child = HydrationCtx::id();
let initial = {
// no resources were read under this, so just return the child
@@ -118,8 +119,7 @@ where
}
};
HydrationCtx::continue_from(current_id.clone());
HydrationCtx::continue_from(after_original_child);
initial
}
}

View File

@@ -167,6 +167,57 @@ impl RuntimeId {
)
}
#[track_caller]
pub(crate) fn create_many_signals_with_map<T, U>(
self,
cx: Scope,
values: impl IntoIterator<Item = T>,
map_fn: impl Fn((ReadSignal<T>, WriteSignal<T>)) -> U,
) -> Vec<U>
where
T: Any + 'static,
{
with_runtime(self, move |runtime| {
let mut signals = runtime.signals.borrow_mut();
let properties = runtime.scopes.borrow();
let mut properties = properties
.get(cx.id)
.expect(
"tried to add signals to a scope that has been disposed",
)
.borrow_mut();
let values = values.into_iter();
let size = values.size_hint().0;
signals.reserve(size);
properties.reserve(size);
values
.map(|value| signals.insert(Rc::new(RefCell::new(value))))
.map(|id| {
properties.push(ScopeProperty::Signal(id));
(
ReadSignal {
runtime: self,
id,
ty: PhantomData,
#[cfg(debug_assertions)]
defined_at: std::panic::Location::caller(),
},
WriteSignal {
runtime: self,
id,
ty: PhantomData,
#[cfg(debug_assertions)]
defined_at: std::panic::Location::caller(),
},
)
})
.map(map_fn)
.collect()
})
.expect("tried to create a signal in a runtime that has been disposed")
}
#[track_caller]
pub(crate) fn create_rw_signal<T>(self, value: T) -> RwSignal<T>
where
T: Any + 'static,

View File

@@ -69,6 +69,50 @@ pub fn create_signal<T>(
s
}
/// Works exactly as [create_signal], but creates multiple signals at once.
#[cfg_attr(
debug_assertions,
instrument(
level = "trace",
skip_all,
fields(
scope = ?cx.id,
ty = %std::any::type_name::<T>()
)
)
)]
#[track_caller]
pub fn create_many_signals<T>(
cx: Scope,
values: impl IntoIterator<Item = T>,
) -> Vec<(ReadSignal<T>, WriteSignal<T>)> {
cx.runtime.create_many_signals_with_map(cx, values, |x| x)
}
/// Works exactly as [create_many_signals], but applies the map function to each signal pair.
#[cfg_attr(
debug_assertions,
instrument(
level = "trace",
skip_all,
fields(
scope = ?cx.id,
ty = %std::any::type_name::<T>()
)
)
)]
#[track_caller]
pub fn create_many_signals_mapped<T, U>(
cx: Scope,
values: impl IntoIterator<Item = T>,
map_fn: impl Fn((ReadSignal<T>, WriteSignal<T>)) -> U + 'static,
) -> Vec<U>
where
T: 'static,
{
cx.runtime.create_many_signals_with_map(cx, values, map_fn)
}
/// Creates a signal that always contains the most recent value emitted by a
/// [Stream](futures::stream::Stream).
/// If the stream has not yet emitted a value since the signal was created, the signal's