Prevent create_signal_from_stream from panicking on SSR

This commit is contained in:
Greg Johnston 2023-01-08 17:09:04 -05:00
parent aa7c7367dc
commit 32ec9cc57e
2 changed files with 24 additions and 10 deletions

View file

@ -209,8 +209,8 @@ pub fn MultiuserCounter(cx: Scope) -> impl IntoView {
};
#[cfg(feature = "ssr")]
let multiplayer_value =
create_signal_from_stream(cx, futures::stream::once(Box::pin(async { 0.to_string() })));
let (multiplayer_value, _) =
create_signal(cx, None::<i32>);
view! {
cx,

View file

@ -1,8 +1,9 @@
use crate::{
debug_warn,
runtime::{with_runtime, RuntimeId},
spawn_local, Runtime, Scope, ScopeProperty, UntrackedGettableSignal, UntrackedSettableSignal,
Runtime, Scope, ScopeProperty, UntrackedGettableSignal, UntrackedSettableSignal,
};
use cfg_if::cfg_if;
use futures::Stream;
use std::{fmt::Debug, marker::PhantomData};
use thiserror::Error;
@ -67,6 +68,9 @@ pub fn create_signal<T>(cx: Scope, value: T) -> (ReadSignal<T>, WriteSignal<T>)
/// [Stream](futures::stream::Stream).
/// If the stream has not yet emitted a value since the signal was created, the signal's
/// value will be `None`.
///
/// **Note**: If used on the server side during server rendering, this will return `None`
/// immediately and not begin driving the stream.
#[cfg_attr(
debug_assertions,
instrument(
@ -79,17 +83,27 @@ pub fn create_signal<T>(cx: Scope, value: T) -> (ReadSignal<T>, WriteSignal<T>)
)]
pub fn create_signal_from_stream<T>(
cx: Scope,
#[allow(unused_mut)] // allowed because needed for SSR
mut stream: impl Stream<Item = T> + Unpin + 'static,
) -> ReadSignal<Option<T>> {
use futures::StreamExt;
cfg_if! {
if #[cfg(feature = "ssr")] {
_ = stream;
let (read, _) = create_signal(cx, None);
read
} else {
use crate::spawn_local;
use futures::StreamExt;
let (read, write) = create_signal(cx, None);
spawn_local(async move {
while let Some(value) = stream.next().await {
write.set(Some(value));
let (read, write) = create_signal(cx, None);
spawn_local(async move {
while let Some(value) = stream.next().await {
write.set(Some(value));
}
});
read
}
});
read
}
}
/// The getter for a reactive signal.