Assim como você pode passar argumentos para uma função, você pode passar props para um componente que personaliza seu comportamento! Os componentes que vimos até agora não aceitam props – então vamos escrever alguns componentes que aceitam.
#[derive(Props)]
Props de componente são uma única estrutura anotada com #[derive(Props)]
. Para um componente aceitar props, o tipo de seu argumento deve ser Scope<YourPropsStruct>
. Então, você pode acessar o valor das props usando cx.props
.
Existem 2 tipos de estruturas Props:
props
próprios:
PartialEq
, permitindo a memoização (se os props não mudarem, o Dioxus não renderizará novamente o componente)props
emprestados:
Props próprios são muito simples – eles não emprestam nada. Exemplo:
{{#include ../../../examples/component_owned_props.rs:Likes}}
Você pode então passar valores de prop para o componente da mesma forma que você passaria atributos para um elemento:
{{#include ../../../examples/component_owned_props.rs:App}}
Possuir props funciona bem se seus props forem fáceis de copiar – como um único número. Mas e se precisarmos passar um tipo de dados maior, como uma String
de um componente App
para um subcomponente TitleCard
? Uma solução ingênua pode ser .clone()
a String
, criando uma cópia dela para o subcomponente – mas isso seria ineficiente, especialmente para Strings
maiores.
Rust permite algo mais eficiente – emprestar a String
como um &str
– é para isso que servem as props emprestadas!
{{#include ../../../examples/component_borrowed_props.rs:TitleCard}}
Podemos então usar o componente assim:
{{#include ../../../examples/component_borrowed_props.rs:App}}
A macro #[derive(Props)]
tem alguns recursos que permitem personalizar o comportamento dos adereços.
Você pode criar campos opcionais usando o tipo Option<…>
para um campo:
{{#include ../../../examples/component_props_options.rs:OptionalProps}}
Em seguida, você pode optar por fornecê-los ou não:
{{#include ../../../examples/component_props_options.rs:OptionalProps_usage}}
Option
Explicitamente ObrigatóriasSe você quiser exigir explicitamente uma Option
, e não uma prop opcional, você pode anotá-la com #[props(!optional)]
:
{{#include ../../../examples/component_props_options.rs:ExplicitOption}}
Então, você tem que passar explicitamente Some("str")
ou None
:
{{#include ../../../examples/component_props_options.rs:ExplicitOption_usage}}
Você pode usar #[props(default = 42)]
para tornar um campo opcional e especificar seu valor padrão:
{{#include ../../../examples/component_props_options.rs:DefaultComponent}}
Então, da mesma forma que props opcionais, você não precisa fornecê-lo:
{{#include ../../../examples/component_props_options.rs:DefaultComponent_usage}}
.into
É comum que as funções Rust aceitem impl Into<SomeType>
em vez de apenas SomeType
para suportar uma ampla gama de parâmetros. Se você quiser uma funcionalidade semelhante com props, você pode usar #[props(into)]
. Por exemplo, você pode adicioná-lo em uma prop String
– e &str
também será aceito automaticamente, pois pode ser convertido em String
:
{{#include ../../../examples/component_props_options.rs:IntoComponent}}
Então, você pode usá-lo assim:
{{#include ../../../examples/component_props_options.rs:IntoComponent_usage}}
inline_props
Até agora, todas as funções Component
que vimos tinham uma struct ComponentProps
correspondente para passar em props. Isso foi bastante verboso... Não seria legal ter props como argumentos de função simples? Então não precisaríamos definir uma estrutura Props, e ao invés de digitar cx.props.whatever
, poderíamos usar whatever
diretamente!
inline_props
permite que você faça exatamente isso. Em vez de digitar a versão "completa":
#[derive(Props, PartialEq)]
struct TitleCardProps {
title: String,
}
fn TitleCard(cx: Scope<TitleCardProps>) -> Element {
cx.render(rsx!{
h1 { "{cx.props.title}" }
})
}
...você pode definir uma função que aceita props como argumentos. Então, basta anotá-lo com #[inline_props]
, e a macro irá transformá-lo em um componente regular para você:
#[inline_props]
fn TitleCard(cx: Scope, title: String) -> Element {
cx.render(rsx!{
h1 { "{title}" }
})
}
Embora o novo Componente seja mais curto e fácil de ler, essa macro não deve ser usada por autores de bibliotecas, pois você tem menos controle sobre a documentação do Prop.