Add PT-BR translations (#456)
* Translate final.md, hello_world.md, README.md, ROADMAP.md and SUMMARY.md * Translatation complete * Internationalization: move guide to en folder and preserve its history. (#494) * Clean files and build mdBook with localization feature * Rebase, remove leftovers and check book builds for every language: ✅ Co-authored-by: Jon Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
1 parent
2369b0cc7f
commit
6ea076fa7f
69 files changed
+4239
-13
No files matched your search
@@ -0,0 +1,26 @@
|
||||
# Hooks Personalizados
|
||||
|
||||
_Hooks_ são uma ótima maneira de encapsular a lógica de negócio. Se nenhum dos _hooks_ existentes funcionar para o seu problema, você pode escrever o seu próprio.
|
||||
|
||||
## Hooks de Composição
|
||||
|
||||
Para evitar a repetição, você pode encapsular a lógica de negócios com base em _hooks_ existentes para criar um novo gancho.
|
||||
|
||||
Por exemplo, se muitos componentes precisam acessar uma _struct_ `AppSettings`, você pode criar um gancho de "atalho":
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_composed.rs:wrap_context}}
|
||||
```
|
||||
|
||||
## Lógica de Hook Personalizada
|
||||
|
||||
Você pode usar [`cx.use_hook`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.Scope.html#method.use_hook) para construir seus próprios _hooks_. Na verdade, é nisso que todos os _hooks_ padrão são construídos!
|
||||
|
||||
`use_hook` aceita um único encerramento para inicializar o _hook_. Ele será executado apenas na primeira vez que o componente for renderizado. O valor de retorno desse encerramento será usado como o valor do _hook_ – o Dioxus o pegará e o armazenará enquanto o componente estiver vivo. Em cada renderização (não apenas na primeira!), você receberá uma referência a esse valor.
|
||||
|
||||
> Nota: Você pode implementar [`Drop`](https://doc.rust-lang.org/std/ops/trait.Drop.html) para o valor do seu _hook_ – ele será descartado e o componente será desmontado (não mais na interface do usuário)
|
||||
|
||||
Dentro do encerramento de inicialização, você normalmente fará chamadas para outros métodos `cx`. Por exemplo:
|
||||
|
||||
- O _hook_ `use_state` rastreia o estado no valor do _hook_ e usa [`cx.schedule_update`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.Scope.html#method.schedule_update) para o Dioxus renderizar novamente o componente sempre que ele for alterado.
|
||||
- O _hook_ `use_context` chama [`cx.consume_context`](https://docs.rs/dioxus/latest/dioxus/prelude/struct.Scope.html#method.consume_context) (que seria custoso chamar em cada render) para obter algum contexto do escopo
|
||||
@@ -0,0 +1,71 @@
|
||||
# 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`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/conditional_rendering.rs:if_else}}
|
||||
```
|
||||
|
||||
> 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:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_children_inspect.rs:Clickable}}
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/conditional_rendering.rs:conditional_none}}
|
||||
```
|
||||
|
||||
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 _booleana_ [`then()`](https://doc.rust-lang.org/std/primitive.bool.html#method.then) 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 com `iter()`)
|
||||
- `.map` o iterador para converter cada item em um `Element` renderizado usando `cx.render(rsx!(...))`
|
||||
- Adicione um atributo `key` exclusivo a cada item do iterador
|
||||
- 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:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rendering_lists.rs:render_list}}
|
||||
```
|
||||
|
||||
### 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.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Manipuladores de eventos
|
||||
|
||||
Eventos são ações interessantes que acontecem, geralmente relacionadas a algo que o usuário fez. Por exemplo, alguns eventos acontecem quando o usuário clica, rola, move o mouse ou digita um caractere. Para responder a essas ações e tornar a interface do usuário interativa, precisamos lidar com esses eventos.
|
||||
|
||||
Os eventos estão associados a elementos. Por exemplo, geralmente não nos importamos com todos os cliques que acontecem em um aplicativo, apenas aqueles em um botão específico. Para lidar com eventos que acontecem em um elemento, devemos anexar o manipulador de eventos desejado a ele.
|
||||
|
||||
Os manipuladores de eventos são semelhantes aos atributos regulares, mas seus nomes geralmente começam com `on` - e aceitam encerramentos como valores. O encerramento será chamado sempre que o evento for acionado e será passado esse evento.
|
||||
|
||||
Por exemplo, para manipular cliques em um elemento, podemos especificar um manipulador `onclick`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_click.rs:rsx}}
|
||||
```
|
||||
|
||||
## O Objeto `Evento`
|
||||
|
||||
Os manipuladores de eventos recebem um objeto [`UiEvent`](https://docs.rs/dioxus-core/latest/dioxus_core/struct.UiEvent.html) contendo informações sobre o evento. Diferentes tipos de eventos contêm diferentes tipos de dados. Por exemplo, eventos relacionados ao mouse contêm [`MouseData`](https://docs.rs/dioxus/latest/dioxus/events/struct.MouseData.html), que informa coisas como onde o mouse foi clicado e quais botões do mouse foram usados.
|
||||
|
||||
No exemplo acima, esses dados de evento foram registrados no terminal:
|
||||
|
||||
```
|
||||
Clicked! Event: UiEvent { data: MouseData { coordinates: Coordinates { screen: (468.0, 109.0), client: (73.0, 25.0), element: (63.0, 15.0), page: (73.0, 25.0) }, modifiers: (empty), held_buttons: EnumSet(), trigger_button: Some(Primary) } }
|
||||
Clicked! Event: UiEvent { data: MouseData { coordinates: Coordinates { screen: (468.0, 109.0), client: (73.0, 25.0), element: (63.0, 15.0), page: (73.0, 25.0) }, modifiers: (empty), held_buttons: EnumSet(), trigger_button: Some(Primary) } }
|
||||
```
|
||||
|
||||
Para saber o que os diferentes tipos de eventos fornecem, leia os [documentos do módulo de eventos](https://docs.rs/dioxus/latest/dioxus/events/index.html).
|
||||
|
||||
### Parando a propagação
|
||||
|
||||
Quando você tem, por exemplo um `button` dentro de um `div`, qualquer clique no `button` também é um clique no `div`. Por esta razão, Dioxus propaga o evento click: primeiro, ele é acionado no elemento alvo, depois nos elementos pai. Se você quiser evitar esse comportamento, você pode chamar `cancel_bubble()` no evento:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_click.rs:rsx}}
|
||||
```
|
||||
|
||||
## Prevenir o Padrão
|
||||
|
||||
Alguns eventos têm um comportamento padrão. Para eventos de teclado, isso pode ser inserir o caractere digitado. Para eventos de mouse, isso pode estar selecionando algum texto.
|
||||
|
||||
Em alguns casos, você pode querer evitar esse comportamento padrão. Para isso, você pode adicionar o atributo `prevent_default` com o nome do manipulador cujo comportamento padrão você deseja interromper. Este atributo é especial: você pode anexá-lo várias vezes para vários atributos:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_prevent_default.rs:prevent_default}}
|
||||
```
|
||||
|
||||
Quaisquer manipuladores de eventos ainda serão chamados.
|
||||
|
||||
> Normalmente, em React ou JavaScript, você chamaria "preventDefault" no evento no retorno de chamada. Dioxus atualmente _não_ suporta este comportamento. Observação: isso significa que você não pode impedir condicionalmente o comportamento padrão.
|
||||
|
||||
## Manipulador de Props
|
||||
|
||||
Às vezes, você pode querer criar um componente que aceite um manipulador de eventos. Um exemplo simples seria um componente `FancyButton`, que aceita um manipulador `on_click`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_handler_prop.rs:component_with_handler}}
|
||||
```
|
||||
|
||||
Então, você pode usá-lo como qualquer outro manipulador:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_handler_prop.rs:usage}}
|
||||
```
|
||||
|
||||
> Nota: assim como qualquer outro atributo, você pode nomear os manipuladores como quiser! Embora eles devam começar com `on`, para que o prop seja automaticamente transformado em um `EventHandler` no local da chamada.
|
||||
>
|
||||
> Você também pode colocar dados personalizados no evento, em vez de, por exemplo, `MouseData`
|
||||
@@ -0,0 +1,87 @@
|
||||
# Hooks e Estado do Componente
|
||||
|
||||
Até agora nossos componentes, sendo funções Rust, não tinham estado – eles estavam sempre renderizando a mesma coisa. No entanto, em um componente de interface do usuário, geralmente é útil ter uma funcionalidade com estado para criar interações do usuário. Por exemplo, você pode querer rastrear se o usuário abriu uma lista suspensa e renderizar coisas diferentes de acordo.
|
||||
|
||||
Para lógica com estado, você pode usar _hooks_. _Hooks_ são funções Rust que fazem referência a `ScopeState` (em um componente, você pode passar `&cx`), e fornecem funcionalidade e estado.
|
||||
|
||||
## Hook `use_state`
|
||||
|
||||
[`use_state`](https://docs.rs/dioxus/latest/dioxus/hooks/fn.use_state.html) é um dos _hooks_ mais simples.
|
||||
|
||||
- Você fornece um fechamento que determina o valor inicial
|
||||
- `use_state` fornece o valor atual e uma maneira de atualizá-lo, definindo-o para outra coisa
|
||||
- Quando o valor é atualizado, `use_state` faz o componente renderizar novamente e fornece o novo valor
|
||||
|
||||
Por exemplo, você pode ter visto o exemplo do contador, no qual o estado (um número) é rastreado usando o _hook_ `use_state`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_counter.rs:component}}
|
||||
```
|
||||
|
||||

|
||||
|
||||
Toda vez que o estado do componente muda, ele é renderizado novamente e a função do componente é chamada, para que você possa descrever como deseja que a nova interface do usuário se pareça. Você não precisa se preocupar em "mudar" nada - apenas descreva o que você quer em termos de estado, e Dioxus cuidará do resto!
|
||||
|
||||
> `use_state` retorna seu valor envolto em uma _smart pointer_ do tipo [`UseState`](https://docs.rs/dioxus/latest/dioxus/hooks/struct.UseState.html). É por isso que você pode ler o valor e atualizá-lo, mesmo dentro de um manipulador.
|
||||
|
||||
Você pode usar vários _hooks_ no mesmo componente se quiser:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_counter_two_state.rs:component}}
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Regras dos Hooks
|
||||
|
||||
O exemplo acima pode parecer um pouco mágico, já que as funções Rust normalmente não estão associadas ao estado. O Dioxus permite que os _hooks_ mantenham o estado entre as renderizações através de uma referência a `ScopeState`, e é por isso que você deve passar `&cx` para eles.
|
||||
|
||||
Mas como Dioxus pode diferenciar entre vários _hooks_ no mesmo componente? Como você viu no segundo exemplo, ambas as funções `use_state` foram chamadas com os mesmos parâmetros, então como elas podem retornar coisas diferentes quando os contadores são diferentes?
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_counter_two_state.rs:use_state_calls}}
|
||||
```
|
||||
|
||||
Isso só é possível porque os dois _hooks_ são sempre chamados na mesma ordem, então Dioxus sabe qual é qual. Portanto, a ordem em que você chama os _hooks_ é importante, e é por isso que você deve seguir certas regras ao usar os _hooks_:
|
||||
|
||||
1. _Hooks_ só podem ser usados em componentes ou outros _hooks_ (falaremos disso mais tarde)
|
||||
2. Em cada chamada para a função componente
|
||||
1. Os mesmos _hooks_ devem ser chamados
|
||||
2. Na mesma ordem
|
||||
3. Os nomes dos _hooks_ devem começar com `use_` para que você não os confunda acidentalmente com funções normais
|
||||
|
||||
Essas regras significam que há certas coisas que você não pode fazer com _hooks_:
|
||||
|
||||
### Sem Hooks em Condicionais
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_bad.rs:conditional}}
|
||||
```
|
||||
|
||||
### Sem Hooks em Closures
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_bad.rs:closure}}
|
||||
```
|
||||
|
||||
### Sem Hooks em Loops
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_bad.rs:loop}}
|
||||
```
|
||||
|
||||
## Gancho `use_ref`
|
||||
|
||||
`use_state` é ótimo para rastrear valores simples. No entanto, você pode notar na [`UseState` API](https://docs.rs/dioxus/latest/dioxus/hooks/struct.UseState.html) que a única maneira de modificar seu valor é substituí-lo por algo else (por exemplo, chamando `set`, ou através de um dos operadores `+=`, `-=`). Isso funciona bem quando é barato construir um valor (como qualquer primitivo). Mas e se você quiser manter dados mais complexos no estado dos componentes?
|
||||
|
||||
Por exemplo, suponha que queremos manter um `Vec` de valores. Se o armazenamos com `use_state`, a única maneira de adicionar um novo valor à lista seria criar um novo `Vec` com o valor adicional e colocá-lo no estado. Isto é custoso! Queremos modificar o `Vec` existente.
|
||||
|
||||
Felizmente, existe outro _hook_ para isso, `use_ref`! É semelhante ao `use_state`, mas permite obter uma referência mutável aos dados contidos.
|
||||
|
||||
Aqui está um exemplo simples que mantém uma lista de eventos em um `use_ref`. Podemos adquirir acesso de escrita ao estado com `.write()`, e então apenas `.push` um novo valor para o estado:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_use_ref.rs:component}}
|
||||
```
|
||||
|
||||
> Os valores de retorno de `use_state` e `use_ref`, (`UseState` e `UseRef`, respectivamente) são de alguma forma semelhantes a [`Cell`](https://doc.rust-lang.org/std/ cell/) e [`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) – eles fornecem mutabilidade interior. No entanto, esses _wrappers_ do Dioxus também garantem que o componente seja renderizado novamente sempre que você alterar o estado.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 362 KiB |
@@ -0,0 +1,3 @@
|
||||
# Interatividade
|
||||
|
||||
Até agora, aprendemos como descrever a estrutura e as propriedades de nossas interfaces de usuário. No entanto, a maioria das interfaces precisa ser interativa para ser útil. Neste capítulo, descrevemos como fazer um aplicativo Dioxus que responde ao usuário.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Roteador
|
||||
|
||||
Em muitos de seus aplicativos, você desejará ter diferentes "cenas". Para uma página da Web, essas cenas podem ser as diferentes páginas da Web com seu próprio conteúdo.
|
||||
|
||||
Você pode escrever sua própria solução de gerenciamento de cena também. No entanto, para poupar o seu esforço, o Dioxus oferece suporte a uma solução de primeira linha para gerenciamento de cena chamada Dioxus Router.
|
||||
|
||||
## O que é isso?
|
||||
|
||||
Para um aplicativo como a página de destino do Dioxus (https://dioxuslabs.com), queremos ter páginas diferentes. Um esboço rápido de um aplicativo seria algo como:
|
||||
|
||||
- Pagina inicial
|
||||
- Blogue
|
||||
- Exemplo de vitrine
|
||||
|
||||
Cada uma dessas cenas é independente – não queremos renderizar a página inicial e o blog ao mesmo tempo.
|
||||
|
||||
É aqui que a `crates` do roteador são úteis. Para ter certeza de que estamos usando o roteador, basta adicionar o recurso `router` à sua dependência do Dioxus.
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
dioxus = { version = "0.2", features = ["desktop", "router"] }
|
||||
```
|
||||
|
||||
## Usando o Roteador
|
||||
|
||||
Ao contrário de outros roteadores no ecossistema Rust, nosso roteador é construído de forma declarativa. Isso torna possível compor o layout do nosso aplicativo simplesmente organizando os componentes.
|
||||
|
||||
```rust
|
||||
rsx!{
|
||||
Router {
|
||||
Route { to: "/home", Home {} }
|
||||
Route { to: "/blog", Blog {} }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Sempre que visitamos este aplicativo, obteremos o componente Home ou o componente Blog renderizado, dependendo de qual rota entrarmos. Se nenhuma dessas rotas corresponder à localização atual, nada será renderizado.
|
||||
|
||||
Podemos corrigir isso de duas maneiras:
|
||||
|
||||
- Uma página 404 de _fallback_
|
||||
|
||||
```rust
|
||||
rsx!{
|
||||
Router {
|
||||
Route { to: "/home", Home {} }
|
||||
Route { to: "/blog", Blog {} }
|
||||
Route { to: "", NotFound {} }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Redirecionar 404 para _Home_
|
||||
|
||||
```rust
|
||||
rsx!{
|
||||
Router {
|
||||
Route { to: "/home", Home {} }
|
||||
Route { to: "/blog", Blog {} }
|
||||
Redirect { from: "", to: "/home" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
Para que nosso aplicativo navegue nessas rotas, podemos fornecer elementos clicáveis chamados Links. Eles simplesmente envolvem elementos `<a>` que, quando clicados, navegam no aplicativo para o local determinado.
|
||||
|
||||
```rust
|
||||
rsx!{
|
||||
Link {
|
||||
to: "/home",
|
||||
"Go home!"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Mais leitura
|
||||
|
||||
Esta página é apenas uma breve visão geral do roteador para mostrar que existe uma solução poderosa já construída para um problema muito comum. Para obter mais informações sobre o roteador, confira seu livro ou confira alguns dos exemplos.
|
||||
|
||||
O roteador tem sua própria documentação! [Disponível aqui](https://dioxuslabs.com/router/guide/).
|
||||
@@ -0,0 +1,71 @@
|
||||
# Estado de compartilhamento
|
||||
|
||||
Muitas vezes, vários componentes precisam acessar o mesmo estado. Dependendo de suas necessidades, existem várias maneiras de implementar isso.
|
||||
|
||||
## Elevenado o Estado
|
||||
|
||||
Uma abordagem para compartilhar o estado entre os componentes é "elevá-lo" até o ancestral comum mais próximo. Isso significa colocar o _hook_ `use_state` em um componente pai e passar os valores necessários como _props_.
|
||||
|
||||
Por exemplo, suponha que queremos construir um editor de memes. Queremos ter uma entrada para editar a legenda do meme, mas também uma visualização do meme com a legenda. Logicamente, o meme e a entrada são 2 componentes separados, mas precisam acessar o mesmo estado (a legenda atual).
|
||||
|
||||
> Claro, neste exemplo simples, poderíamos escrever tudo em um componente - mas é melhor dividir tudo em componentes menores para tornar o código mais reutilizável e fácil de manter (isso é ainda mais importante para aplicativos maiores e complexos) .
|
||||
|
||||
Começamos com um componente `Meme`, responsável por renderizar um meme com uma determinada legenda:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor.rs:meme_component}}
|
||||
```
|
||||
|
||||
> Observe que o componente `Meme` não sabe de onde vem a legenda – ela pode ser armazenada em `use_state`, `use_ref` ou uma constante. Isso garante que seja muito reutilizável - o mesmo componente pode ser usado para uma galeria de memes sem nenhuma alteração!
|
||||
|
||||
Também criamos um editor de legendas, totalmente desacoplado do meme. O editor de legendas não deve armazenar a legenda em si – caso contrário, como iremos fornecê-la ao componente `Meme`? Em vez disso, ele deve aceitar a legenda atual como um suporte, bem como um manipulador de eventos para delegar eventos de entrada para:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor.rs:caption_editor}}
|
||||
```
|
||||
|
||||
Finalmente, um terceiro componente renderizará os outros dois como filhos. Ele será responsável por manter o estado e passar os _props_ relevantes.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor.rs:meme_editor}}
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Usando o contexto
|
||||
|
||||
Às vezes, algum estado precisa ser compartilhado entre vários componentes na árvore, e passá-lo pelos _props_ é muito inconveniente.
|
||||
|
||||
Suponha agora que queremos implementar uma alternância de modo escuro para nosso aplicativo. Para conseguir isso, faremos com que cada componente selecione o estilo dependendo se o modo escuro está ativado ou não.
|
||||
|
||||
> Nota: estamos escolhendo esta abordagem como exemplo. Existem maneiras melhores de implementar o modo escuro (por exemplo, usando variáveis CSS). Vamos fingir que as variáveis CSS não existem – bem-vindo a 2013!
|
||||
|
||||
Agora, poderíamos escrever outro `use_state` no componente superior e passar `is_dark_mode` para cada componente através de _props_. Mas pense no que acontecerá à medida que o aplicativo crescer em complexidade – quase todos os componentes que renderizam qualquer CSS precisarão saber se o modo escuro está ativado ou não – para que todos precisem do mesmo suporte do modo escuro. E cada componente pai precisará passá-lo para eles. Imagine como isso ficaria confuso e verboso, especialmente se tivéssemos componentes com vários níveis de profundidade!
|
||||
|
||||
A Dioxus oferece uma solução melhor do que esta "perfuração com hélice" – fornecendo contexto. O _hook_ [`use_context_provider`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_context_provider.html) é semelhante ao `use_ref`, mas o torna disponível através do [`use_context`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_context.html) para todos os componentes filhos.
|
||||
|
||||
Primeiro, temos que criar um _struct_ para nossa configuração de modo escuro:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:DarkMode_struct}}
|
||||
```
|
||||
|
||||
Agora, em um componente de nível superior (como `App`), podemos fornecer o contexto `DarkMode` para todos os componentes filhos:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:context_provider}}
|
||||
```
|
||||
|
||||
Como resultado, qualquer componente filho de `App` (direto ou não), pode acessar o contexto `DarkMode`.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:use_context}}
|
||||
```
|
||||
|
||||
> `use_context` retorna `Option<UseSharedState<DarkMode>>` aqui. Se o contexto foi fornecido, o valor é `Some(UseSharedState)`, que você pode chamar `.read` ou `.write`, similarmente a `UseRef`. Caso contrário, o valor é `None`.
|
||||
|
||||
Por exemplo, aqui está como implementaríamos a alternância do modo escuro, que lê o contexto (para determinar a cor que deve renderizar) e grava nele (para alternar o modo escuro):
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:toggle}}
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# Entradas do Usuário
|
||||
|
||||
As interfaces geralmente precisam fornecer uma maneira de inserir dados: por exemplo, texto, números, caixas de seleção, etc. No Dioxus, há duas maneiras de trabalhar com a entrada do usuário.
|
||||
|
||||
## Entradas Controladas
|
||||
|
||||
Com entradas controladas, você fica diretamente responsável pelo estado da entrada. Isso lhe dá muita flexibilidade e facilita manter as coisas em sincronia. Por exemplo, é assim que você criaria uma entrada de texto controlada:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/input_controlled.rs:component}}
|
||||
```
|
||||
|
||||
Observe a flexibilidade - você pode:
|
||||
|
||||
- Exibir o mesmo conteúdo em outro elemento, e eles estarão em sincronia
|
||||
- Transformar a entrada toda vez que for modificada (por exemplo, para garantir que seja maiúscula)
|
||||
- Validar a entrada toda vez que ela mudar
|
||||
- Ter uma lógica personalizada acontecendo quando a entrada for alterada (por exemplo, solicitação de rede para preenchimento automático)
|
||||
- Alterar programaticamente o valor (por exemplo, um botão "randomize" que preenche a entrada com absurdos)
|
||||
|
||||
## Entradas não Controladas
|
||||
|
||||
Como alternativa às entradas controladas, você pode simplesmente deixar a plataforma acompanhar os valores de entrada. Se não dissermos a uma entrada HTML qual conteúdo ela deve ter, ela poderá ser editada de qualquer maneira (isso está embutido na visualização da web). Essa abordagem pode ser mais eficiente, mas menos flexível. Por exemplo, é mais difícil manter a entrada sincronizada com outro elemento.
|
||||
|
||||
Como você não tem necessariamente o valor atual da entrada não controlada no estado, você pode acessá-lo ouvindo os eventos `oninput` (de maneira semelhante aos componentes controlados) ou, se a entrada for parte de um formulário, você pode acessar os dados do formulário nos eventos do formulário (por exemplo, `oninput` ou `onsubmit`):
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/input_uncontrolled.rs:component}}
|
||||
```
|
||||
|
||||
```
|
||||
Submitted! UiEvent { data: FormData { value: "", values: {"age": "very old", "date": "1966", "name": "Fred"} } }
|
||||
```
|
||||
Reference in new issue
Block a user