Attribute Macro avalanche::component[][src]

#[component]
Expand description

An attribute macro used to define components.

Basic usage

The macro must be applied to a function that returns a View. It generates a struct implementing Component with the name of the input function, and a builder struct. The function’s name should start with a capital ASCII character.

The function can optionally take parameters. Parameter types must be Clone and 'static. Parameters must have concrete types: they cannot use the impl Trait syntax. Components cannot be async or generic.

A component must return a View describing what it will render. Components are invoked with the same syntax as function calls, except with the macro ! after the type name:

use avalanche::{component, tracked, View};
use avalanche_web::components::{H1, Text};

const class: &str = "hello-world";

#[component]
pub fn HelloWorld(name: String) -> View {
    H1!(
        id: class,
        class: class,
        child: Text!(format!("Hi there, {}!", tracked!(name)))
    )
}

In the case of H1, all of its parameters are optional and have default values, but for components generated by this macro, all parameters must be provided, or component instantiation will panic at runtime. In the future, this will instead be a compile-time error.

Note that all macro invocations beginning with a capital ASCII character will be interpreted as component invocations within the function. If you need to invoke a macro beginning with a capital letter, consider using it with an alias beginning with _.

Tracked values

Parameter values are passed into a function with the Tracked wrapper. More details on how that works is found in the tracked macro documentation.

Avoid side effects and mutability

avalanche considers a parameter updated if one of the parameters or hooks that influence it change, but a function like rand::thread_rng has a different value on every call despite having no parameter or hook dependencies. Using values from functions and methods that are not pure or mutate values will lead to missed updates. Instead, create new variables: use let string = string + " appended" instead of string += "appended". If you need to use mutation in a component, including interior mutability, use the state hook.

Eschew third-party macros

Unfortunately, macros are syntax extensions and component cannot keep track of tracked variables in most of them. All std macros (like vec! and format!) and avalanche macros (like enclose!()) work well, but any others may lead to parameters being incorrectly marked as not updated.