Skip to content

v0.5.0-rc1

Pre-release
Pre-release

Choose a tag to compare

@gbj gbj released this 12 Sep 02:04
· 2513 commits to main since this release

I'm planning on releasing 0.5.0 proper toward the end of this week. However, we've continued having some really good new features and some changes, so I want to give it some additional time for testing rather than rushing and breaking things.

For overall 0.5.0 changes, see here.

New Features in this Release

attr: on components, and spreading attributes

Makes it much easier to pass some set of attributes to be given to a component (with attr: passed into a #[prop(attrs)] prop), and then to spread them onto an element with {..attrs} syntax.

#[component]
pub fn App() -> impl IntoView {
    view! {
        <Input attr:value="hello" attr:label="foo" />
        <Input attr:type="number" attr:value="0" />
    }
}

#[component]
pub fn Input(
    #[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
) -> impl IntoView {
    view! {
        <input {..attrs} />
        <pre>{format!("{attrs2:#?}")}</pre>
    }
}

Generics on components in view

Newly added support for syntax that identifies a generic type for a component in the view

#[component]
pub fn GenericComponent<S>(#[prop(optional)] ty: PhantomData<S>) -> impl IntoView {
    std::any::type_name::<S>()
}

#[component]
pub fn App() -> impl IntoView {
    view! {
        <GenericComponent<String>/>
        <GenericComponent<usize>/>
        <GenericComponent<i32>/>
    }
}

Callback types

These make it easier to add things like optional callback functions to components.

#[component]
pub fn App() -> impl IntoView {
    view! {
        <ShowOptFall when=|| { 5 < 3 } fallback=|_| view! { <p>"YES"</p> }>
            <p>"NO"</p>
        </ShowOptFall>
        <ShowOptFall when=|| { 5 < 3 }>
            <p>"NO"</p>
        </ShowOptFall>
        <ShowOptFall when=||{ 5 > 3 }>
            <p>"YES"</p>
        </ShowOptFall>
    }
}

#[component]
pub fn ShowOptFall<W>(
    /// The components Show wraps
    children: Box<dyn Fn() -> Fragment>,
    /// A closure that returns a bool that determines whether this thing runs
    when: W,
    /// A closure that returns what gets rendered if the when statement is false
    #[prop(optional, into)]
    fallback: Option<ViewCallback<()>>,
) -> impl IntoView
where
    W: Fn() -> bool + 'static,
{
    let memoized_when = create_memo(move |_| when());

    move || match memoized_when.get() {
        true => children().into_view(),
        false => match fallback.as_ref() {
            Some(fallback) => fallback.call(()).into_view(),
            None => ().into_view(),
        },
    }
}

with!() and update!() macros

Nested .withI() calls are a pain. Now you can do

let (first, _) = create_signal("Bob".to_string());
let (middle, _) = create_signal("J.".to_string());
let (last, _) = create_signal("Smith".to_string());
let name = move || with!(|first, middle, last| format!("{first} {middle} {last}"));

instead of

let name = move || {
	first.with(|first| {
		middle.with(|middle| last.with(|last| format!("{first} {middle} {last}")))
	})
};

Rustier interfaces for signal types

This framework's origins as a Rust port of SolidJS mean we've inherited some functional-JS-isms. Combined with the need to pass cx everywhere prior to 0.5 this has tended to mean we've gone with create_ and so on rather than Rusty ::new(). This simply adds a few Rustier constructors like

let count = RwSignal::new(0);
let double_count = Memo::new(move |_| count() * 2);

Breaking Changes

  • Renaming .derived_signal() and .mapped_signal_setter() to the more idiomatic .into_signal() and .into_signal_setter()
  • Memoizing whether Suspense is ready yet or not in order to avoid over-re-rendering. Shouldn't break your app, but if something weird happens let me know.
  • Changes timing of create_effect so that it runs a tick after it is created, which solves a number of timing issues with effects that had previously led to create_effect(move || request_animation_frame(move || /* */))

What's Changed

New Contributors

Full Changelog: v0.5.0-beta...v0.5.0-rc1