Skip to main content
Version: Next

From 0.21.0 to 0.22.0

MSRV raised to 1.84.0

The minimum supported Rust version is now 1.84.0. Update your toolchain:

rustup update stable

#[function_component] renamed to #[component]

The #[function_component] attribute has been renamed to #[component] for brevity. The old name is deprecated but still works.

Automated refactor

# Using sed (simple but also replaces in comments/strings)
find . -name "*.rs" -exec sed -i 's/#\[function_component\]/#[component]/g' {} +
find . -name "*.rs" -exec sed -i 's/#\[function_component(/#[component(/g' {} +

# Or using ast-grep (recommended - AST-aware, preserves comments/strings)
# Important: Run the named pattern FIRST to preserve component names
ast-grep run -p '#[function_component($$$ARGS)]' -r '#[component($$$ARGS)]' -l rust --update-all .
ast-grep run -p '#[function_component]' -r '#[component]' -l rust --update-all .
備註

The sed commands will also replace occurrences in comments and strings. Use ast-grep for more precise refactoring.

#[function_component]
fn MyComponent() -> Html {
html! { <div>{"Hello"}</div> }
}

#[function_component(Named)]
fn AnotherComponent() -> Html {
html! { <div>{"World"}</div> }
}

class=(...) syntax removed

The deprecated class=(expr) syntax has been removed. Use class={classes!(...)} instead.

Finding occurrences

# Find all files using the old class=(...) syntax
grep -rn "class=(" --include="*.rs" .

Manual refactor

The transformation is straightforward: wrap the tuple contents with classes!() and change parentheses to braces:

  • class=(a, b)class={classes!(a, b)}
  • class=(expr)class={classes!(expr)}
html! {
<div class=(some_class, other_class)>{"Content"}</div>
}

ToHtml trait removed

The ToHtml trait has been removed. Use IntoPropValue for custom type conversions.

For-loops in html! macro

You can now use for-loops directly in the html! macro. This is optional but provides cleaner syntax:

html! {
<ul>
{ for items.iter().map(|item| html! { <li key={item.id}>{ &item.name }</li> }) }
</ul>
}

use_effect_with no longer requires || () return

Effect hooks no longer require returning || () when there's no cleanup:

use_effect_with(deps, |deps| {
// do something
|| () // had to return this
});