Renderização Dinâmica
Às vezes você quer renderizar coisas diferentes dependendo do estado/props. Com o Dioxus, apenas descreva o que você quer ver usando o fluxo de controle do Rust – o framework se encarregará de fazer as mudanças necessárias em tempo real se o estado ou props mudarem!
Renderização Condicional
Para renderizar diferentes elementos com base em uma condição, você pode usar uma instrução if-else
:
#![allow(unused)] fn main() { if *is_logged_in { cx.render(rsx! { "Welcome!" button { onclick: move |_| on_log_out.call(()), "Log Out", } }) } else { cx.render(rsx! { button { onclick: move |_| on_log_in.call(()), "Log In", } }) } }
Você também pode usar instruções
match
, ou qualquer função Rust para renderizar condicionalmente coisas diferentes.
Inspecionando props Element
Como Element
é uma Option<VNode>
, os componentes que aceitam Element
como prop podem realmente inspecionar seu conteúdo e renderizar coisas diferentes com base nisso. Exemplo:
#![allow(unused)] fn main() { fn Clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element { match cx.props.children { Some(VNode { dynamic_nodes, .. }) => { todo!("render some stuff") } _ => { todo!("render some other stuff") } } } }
Você não pode modificar o Element
, mas se precisar de uma versão modificada dele, você pode construir um novo baseado em seus atributos/filhos/etc.
Renderizando Nada
Para renderizar nada, você pode retornar None
de um componente. Isso é útil se você deseja ocultar algo condicionalmente:
#![allow(unused)] fn main() { if *is_logged_in { return None; } cx.render(rsx! { a { "You must be logged in to comment" } }) }
Isso funciona porque o tipo Element
é apenas um alias para Option<VNode>
Novamente, você pode usar um método diferente para retornar condicionalmente
None
. Por exemplo, a função booleanathen()
pode ser usada.
Listas de renderização
Frequentemente, você desejará renderizar uma coleção de componentes. Por exemplo, você pode querer renderizar uma lista de todos os comentários em uma postagem.
Para isso, o Dioxus aceita iteradores que produzem Element
s. Então precisamos:
- Obter um iterador sobre todos os nossos itens (por exemplo, se você tiver um
Vec
de comentários, itere sobre ele comiter()
) .map
o iterador para converter cada item em umElement
renderizado usandocx.render(rsx!(...))
- Adicione um atributo
key
exclusivo a cada item do iterador
- Adicione um atributo
- Incluir este iterador no RSX final
Exemplo: suponha que você tenha uma lista de comentários que deseja renderizar. Então, você pode renderizá-los assim:
#![allow(unused)] fn main() { let comment_field = use_state(cx, String::new); let mut next_id = use_state(cx, || 0); let comments = use_ref(cx, Vec::<Comment>::new); let comments_lock = comments.read(); let comments_rendered = comments_lock.iter().map(|comment| { rsx!(CommentComponent { key: "{comment.id}", comment: comment.clone(), }) }); cx.render(rsx!( form { onsubmit: move |_| { comments.write().push(Comment { content: comment_field.get().clone(), id: *next_id.get(), }); next_id += 1; comment_field.set(String::new()); }, input { value: "{comment_field}", oninput: |event| comment_field.set(event.value.clone()), } input { r#type: "submit", } }, comments_rendered, )) }
O Atributo key
Toda vez que você renderiza novamente sua lista, o Dioxus precisa acompanhar qual item foi para onde, porque a ordem dos itens em uma lista pode mudar – itens podem ser adicionados, removidos ou trocados. Apesar disso, Dioxus precisa:
- Acompanhar o estado do componente
- Descobrir com eficiência quais atualizações precisam ser feitas na interface do usuário
Por exemplo, suponha que o CommentComponent
tenha algum estado – ex. um campo onde o usuário digitou uma resposta. Se a ordem dos comentários mudar repentinamente, o Dioxus precisa associar corretamente esse estado ao mesmo comentário – caso contrário, o usuário acabará respondendo a um comentário diferente!
Para ajudar o Dioxus a acompanhar os itens da lista, precisamos associar cada item a uma chave exclusiva. No exemplo acima, geramos dinamicamente a chave exclusiva. Em aplicações reais, é mais provável que a chave venha de, por exemplo, um ID de banco de dados. Realmente não importa de onde você obtém a chave, desde que atenda aos requisitos
- As chaves devem ser únicas em uma lista
- O mesmo item deve sempre ser associado à mesma chave
- As chaves devem ser relativamente pequenas (ou seja, converter toda a estrutura Comment em uma String seria uma chave muito ruim) para que possam ser comparadas com eficiência
Você pode ficar tentado a usar o índice de um item na lista como sua chave. Na verdade, é isso que o Dioxus usará se você não especificar uma chave. Isso só é aceitável se você puder garantir que a lista seja constante – ou seja, sem reordenação, adições ou exclusões.
Observe que se você passar a chave para um componente que você criou, ele não receberá a chave como prop. É usado apenas como uma dica pelo próprio Dioxus. Se o seu componente precisar de um ID, você deve passá-lo como um prop separado.