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:
Breno RochaandJon Kelley authored and GitHub committed 2022-07-11 13:28:12 -04:00
1 parent 2369b0cc7f
commit 6ea076fa7f
69 files changed
+4239 -13

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
# Trabalhando em Assincronia
Muitas vezes, os aplicativos precisam interagir com sistemas de arquivos, interfaces de rede, hardware ou temporizadores. Este capítulo fornece uma visão geral do uso de código assíncrono no Dioxus.
## O Tempo de Execução (runtime)
Por padrão, o Dioxus-Desktop vem com o runtime `Tokio` e configura tudo automaticamente para você. No momento, isso não é configurável, embora seja fácil escrever uma integração para o desktop Dioxus que use um tempo de execução assíncrono diferente.
Dioxus atualmente não é `thread-safe`, então qualquer código assíncrono que você escreve _não_ precisa ser `Send/Sync`. Isso significa que você pode usar estruturas não `thread-safe` como `Cell`, `Rc` e `RefCell`.
+29
View File
@@ -0,0 +1,29 @@
# Gerando Futures
Os **"hooks"** `use_future` e `use_coroutine` são úteis se você quiser gerar incondicionalmente o `Future`. Às vezes, porém, você desejará apenas gerar um `Future` em resposta a um evento, como um clique do mouse. Por exemplo, suponha que você precise enviar uma solicitação quando o usuário clicar em um botão "log in". Para isso, você pode usar `cx.spawn`:
```rust
{{#include ../../examples/spawn.rs:spawn}}
```
> Nota: `spawn` sempre gerará um _novo_ `Future`. Você provavelmente não quer chamá-lo em cada renderização.
O `Future` deve ser `'static` – então quaisquer valores capturados pela tarefa não podem carregar nenhuma referência a `cx`, como um `UseState`.
No entanto, como você normalmente precisa de uma maneira de atualizar o valor de um gancho, você pode usar `to_owned` para criar um clone do _handle_ do _hook_. Você pode então usar esse clone no encerramento assíncrono.
Para tornar isso um pouco menos detalhado, o Dioxus exporta a macro `to_owned!` que criará uma ligação como mostrado acima, o que pode ser bastante útil ao lidar com muitos valores.
```rust
{{#include ../../examples/spawn.rs:to_owned_macro}}
```
Calling `spawn` will give you a `JoinHandle` which lets you cancel or pause the future.
## Gerando Tarefas do Tokio
Às vezes, você pode querer gerar uma tarefa em segundo plano que precise de vários _threads_ ou conversar com o hardware que pode bloquear o código do seu aplicativo. Nesses casos, podemos gerar diretamente uma tarefa Tokio do nosso `Future`. Para Dioxus-Desktop, sua tarefa será gerada no tempo de execução Multi-Tarefado do Tokio:
```rust
{{#include ../../examples/spawn.rs:tokio}}
```
+181
View File
@@ -0,0 +1,181 @@
# Corrotinas
Outra boa ferramenta para manter em sua caixa de ferramentas assíncrona são as corrotinas. Corrotinas são `Futures` que podem ser interrompidos, iniciados, pausados e retomados manualmente.
Assim como os `Futures` regulares, o código em uma corrotina Dioxus será executado até o próximo ponto `await` antes do _render_. Esse controle de baixo nível sobre tarefas assíncronas é bastante poderoso, permitindo tarefas em _loop_ infinito, como pesquisa de WebSocket, temporizadores em segundo plano e outras ações periódicas.
## `use_coroutine`
A configuração básica para corrotinas é o _hook_ `use_coroutine`. A maioria das corrotinas que escrevemos serão _loops_ de pesquisa usando `async`/`await`.
```rust
fn app(cx: Scope) -> Element {
let ws: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
// Connect to some sort of service
let mut conn = connect_to_ws_server().await;
// Wait for data on the service
while let Some(msg) = conn.next().await {
// handle messages
}
});
}
```
Para muitos serviços, um _loop_ assíncrono simples lidará com a maioria dos casos de uso.
No entanto, se quisermos desabilitar temporariamente a corrotina, podemos "pausá-la" usando o método `pause` e "retomá-la" usando o método `resume`:
```rust
let sync: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
// code for syncing
});
if sync.is_running() {
cx.render(rsx!{
button {
onclick: move |_| sync.pause(),
"Disable syncing"
}
})
} else {
cx.render(rsx!{
button {
onclick: move |_| sync.resume(),
"Enable syncing"
}
})
}
```
Esse padrão é onde as corrotinas são extremamente úteis – em vez de escrever toda a lógica complicada para pausar nossas tarefas assíncronas como faríamos com `Promises` de JavaScript, o modelo do Rust nos permite simplesmente não pesquisar nosso `Future`.
## Enviando valores
Você deve ter notado que o encerramento `use_coroutine` recebe um argumento chamado `rx`. O que é aquilo? Bem, um padrão comum em aplicativos complexos é lidar com vários códigos assíncronos de uma só vez. Com bibliotecas como o Redux Toolkit, gerenciar várias promessas ao mesmo tempo pode ser um desafio e uma fonte comum de _bugs_.
Usando corrotinas, temos a oportunidade de centralizar nossa lógica assíncrona. O parâmetro `rx` é um canal ilimitado para código externo à corrotina para enviar dados _para_ a corrotina. Em vez de fazer um _loop_ em um serviço externo, podemos fazer um _loop_ no próprio canal, processando mensagens de dentro de nosso aplicativo sem precisar gerar um novo `Future`. Para enviar dados para a corrotina, chamaríamos "send" no _handle_.
```rust
enum ProfileUpdate {
SetUsername(String),
SetAge(i32)
}
let profile = use_coroutine(&cx, |mut rx: UnboundedReciver<ProfileUpdate>| async move {
let mut server = connect_to_server().await;
while let Ok(msg) = rx.next().await {
match msg {
ProfileUpdate::SetUsername(name) => server.update_username(name).await,
ProfileUpdate::SetAge(age) => server.update_age(age).await,
}
}
});
cx.render(rsx!{
button {
onclick: move |_| profile.send(ProfileUpdate::SetUsername("Bob".to_string())),
"Update username"
}
})
```
Para aplicativos suficientemente complexos, poderíamos criar vários "serviços" úteis diferentes que fazem um _loop_ nos canais para atualizar o aplicativo.
```rust
let profile = use_coroutine(&cx, profile_service);
let editor = use_coroutine(&cx, editor_service);
let sync = use_coroutine(&cx, sync_service);
async fn profile_service(rx: UnboundedReceiver<ProfileCommand>) {
// do stuff
}
async fn sync_service(rx: UnboundedReceiver<SyncCommand>) {
// do stuff
}
async fn editor_service(rx: UnboundedReceiver<EditorCommand>) {
// do stuff
}
```
Podemos combinar corrotinas com `Fermi` para emular o sistema `Thunk` do **Redux Toolkit** com muito menos dor de cabeça. Isso nos permite armazenar todo o estado do nosso aplicativo _dentro_ de uma tarefa e, em seguida, simplesmente atualizar os valores de "visualização" armazenados em `Atoms`. Não pode ser subestimado o quão poderosa é essa técnica: temos todas as vantagens das tarefas nativas do Rust com as otimizações e ergonomia do estado global. Isso significa que seu estado _real_ não precisa estar vinculado a um sistema como `Fermi` ou `Redux` – os únicos `Atoms` que precisam existir são aqueles que são usados para controlar a interface.
```rust
static USERNAME: Atom<String> = |_| "default".to_string();
fn app(cx: Scope) -> Element {
let atoms = use_atom_root(&cx);
use_coroutine(&cx, |rx| sync_service(rx, atoms.clone()));
cx.render(rsx!{
Banner {}
})
}
fn Banner(cx: Scope) -> Element {
let username = use_read(&cx, USERNAME);
cx.render(rsx!{
h1 { "Welcome back, {username}" }
})
}
```
Agora, em nosso serviço de sincronização, podemos estruturar nosso estado como quisermos. Só precisamos atualizar os valores da _view_ quando estiver pronto.
```rust
enum SyncAction {
SetUsername(String),
}
async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
let username = atoms.write(USERNAME);
let errors = atoms.write(ERRORS);
while let Ok(msg) = rx.next().await {
match msg {
SyncAction::SetUsername(name) => {
if set_name_on_server(&name).await.is_ok() {
username.set(name);
} else {
errors.make_mut().push("SetUsernameFailed");
}
}
}
}
}
```
## Valores de Rendimento
Para obter valores de uma corrotina, basta usar um identificador `UseState` e definir o valor sempre que sua corrotina concluir seu trabalho.
```rust
let sync_status = use_state(&cx, || Status::Launching);
let sync_task = use_coroutine(&cx, |rx: UnboundedReceiver<SyncAction>| {
to_owned![sync_status];
async move {
loop {
delay_ms(1000).await;
sync_status.set(Status::Working);
}
}
})
```
## Injeção Automática na API de Contexto
Os identificadores de corrotina são injetados automaticamente por meio da API de contexto. `use_coroutine_handle` com o tipo de mensagem como genérico pode ser usado para buscar um _handle_.
```rust
fn Child(cx: Scope) -> Element {
let sync_task = use_coroutine_handle::<SyncAction>(&cx);
sync_task.send(SyncAction::SetUsername);
}
```
+31
View File
@@ -0,0 +1,31 @@
# `UseFuture`
[`use_future`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_future.html) permite executar um encerramento assíncrono e fornece seu resultado.
Por exemplo, podemos fazer uma solicitação de API dentro de `use_future`:
```rust
{{#include ../../examples/use_future.rs:use_future}}
```
O código dentro de `use_future` será enviado ao agendador do Dioxus assim que o componente for renderizado.
Podemos usar `.value()` para obter o resultado do `Future`. Na primeira execução, como não há dados prontos quando o componente é carregado, seu valor será `None`. No entanto, uma vez finalizado o `Future`, o componente será renderizado novamente e o valor agora será `Some(...)`, contendo o valor de retorno do encerramento.
Podemos então renderizar esse resultado:
```rust
{{#include ../../examples/use_future.rs:render}}
```
## Reiniciando o `Future`
O identificador `UseFuture` fornece um método `restart`. Ele pode ser usado para executar o `Future` novamente, produzindo um novo valor.
## Dependências
Muitas vezes, você precisará executar o `Future` novamente toda vez que algum valor (por exemplo, uma prop) mudar. Ao invés de `.restart` manualmente, você pode fornecer uma tupla de "dependências" para o gancho. Ele executará automaticamente o `Future` quando qualquer uma dessas dependências for alterada. Exemplo:
```rust
{{#include ../../examples/use_future.rs:dependency}}
```