Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 59 additions & 59 deletions src/content/learn/scaling-up-with-reducer-and-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ title: Scaling Up with Reducer and Context

<Intro>

Reducers let you consolidate a component's state update logic. Context lets you pass information deep down to other components. You can combine reducers and context together to manage state of a complex screen.
Reducers permitem consolidar a lógica de atualização de estado de um componente. Context permite passar informações profundamente para outros componentes. Você pode combinar reducers e context juntos para gerenciar o estado de uma tela complexa.

</Intro>

<YouWillLearn>

* How to combine a reducer with context
* How to avoid passing state and dispatch through props
* How to keep context and state logic in a separate file
* Como combinar um reducer com context
* Como evitar passar estado e dispatch através de props
* Como manter a lógica de context e estado em um arquivo separado

</YouWillLearn>

## Combining a reducer with context {/*combining-a-reducer-with-context*/}
## Combinando um reducer com context {/*combining-a-reducer-with-context*/}

In this example from [the introduction to reducers](/learn/extracting-state-logic-into-a-reducer), the state is managed by a reducer. The reducer function contains all of the state update logic and is declared at the bottom of this file:
Neste exemplo da [introdução aos reducers](/learn/extracting-state-logic-into-a-reducer), o estado é gerenciado por um reducer. A função reducer contém toda a lógica de atualização de estado e é declarada no final deste arquivo:

<Sandpack>

Expand Down Expand Up @@ -207,9 +207,9 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

A reducer helps keep the event handlers short and concise. However, as your app grows, you might run into another difficulty. **Currently, the `tasks` state and the `dispatch` function are only available in the top-level `TaskApp` component.** To let other components read the list of tasks or change it, you have to explicitly [pass down](/learn/passing-props-to-a-component) the current state and the event handlers that change it as props.
Um reducer ajuda a manter os manipuladores de eventos curtos e concisos. No entanto, à medida que seu aplicativo cresce, você pode encontrar outra dificuldade. **Atualmente, o estado `tasks` e a função `dispatch` estão disponíveis apenas no componente de nível superior `TaskApp`.** Para permitir que outros componentes leiam a lista de tarefas ou a alterem, você precisa [passar explicitamente](/learn/passing-props-to-a-component) o estado atual e os manipuladores de eventos que o alteram como props.

For example, `TaskApp` passes a list of tasks and the event handlers to `TaskList`:
Por exemplo, `TaskApp` passa uma lista de tarefas e os manipuladores de eventos para `TaskList`:

```js
<TaskList
Expand All @@ -219,7 +219,7 @@ For example, `TaskApp` passes a list of tasks and the event handlers to `TaskLis
/>
```

And `TaskList` passes the event handlers to `Task`:
E `TaskList` passa os manipuladores de eventos para `Task`:

```js
<Task
Expand All @@ -229,30 +229,30 @@ And `TaskList` passes the event handlers to `Task`:
/>
```

In a small example like this, this works well, but if you have tens or hundreds of components in the middle, passing down all state and functions can be quite frustrating!
Em um exemplo pequeno como este, isso funciona bem, mas se você tiver dezenas ou centenas de componentes no meio, passar todas as props de estado e funções pode ser bastante frustrante!

This is why, as an alternative to passing them through props, you might want to put both the `tasks` state and the `dispatch` function [into context.](/learn/passing-data-deeply-with-context) **This way, any component below `TaskApp` in the tree can read the tasks and dispatch actions without the repetitive "prop drilling".**
É por isso que, como alternativa a passá-las através de props, você pode querer colocar tanto o estado `tasks` quanto a função `dispatch` [em um context.](/learn/passing-data-deeply-with-context) **Dessa forma, qualquer componente abaixo de `TaskApp` na árvore pode ler as tarefas e despachar ações sem a repetitiva "prop drilling".**

Here is how you can combine a reducer with context:
Veja como você pode combinar um reducer com context:

1. **Create** the context.
2. **Put** state and dispatch into context.
3. **Use** context anywhere in the tree.
1. **Crie** o context.
2. **Coloque** o estado e o dispatch no context.
3. **Use** o context em qualquer lugar da árvore.

### Step 1: Create the context {/*step-1-create-the-context*/}
### Etapa 1: Crie o context {/*step-1-create-the-context*/}

The `useReducer` Hook returns the current `tasks` and the `dispatch` function that lets you update them:
O Hook `useReducer` retorna o `tasks` atual e a função `dispatch` que permite atualizá-los:

```js
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
```

To pass them down the tree, you will [create](/learn/passing-data-deeply-with-context#step-2-use-the-context) two separate contexts:
Para passá-los pela árvore, você [criará](/learn/passing-data-deeply-with-context#step-2-use-the-context) dois contexts separados:

- `TasksContext` provides the current list of tasks.
- `TasksDispatchContext` provides the function that lets components dispatch actions.
- `TasksContext` fornece a lista atual de tarefas.
- `TasksDispatchContext` fornece a função que permite aos componentes despachar ações.

Export them from a separate file so that you can later import them from other files:
Exporte-os de um arquivo separado para que você possa importá-los posteriormente de outros arquivos:

<Sandpack>

Expand Down Expand Up @@ -448,11 +448,11 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

Here, you're passing `null` as the default value to both contexts. The actual values will be provided by the `TaskApp` component.
Aqui, você está passando `null` como valor padrão para ambos os contexts. Os valores reais serão fornecidos pelo componente `TaskApp`.

### Step 2: Put state and dispatch into context {/*step-2-put-state-and-dispatch-into-context*/}
### Etapa 2: Coloque o estado e o dispatch no context {/*step-2-put-state-and-dispatch-into-context*/}

Now you can import both contexts in your `TaskApp` component. Take the `tasks` and `dispatch` returned by `useReducer()` and [provide them](/learn/passing-data-deeply-with-context#step-3-provide-the-context) to the entire tree below:
Agora você pode importar ambos os contexts em seu componente `TaskApp`. Pegue os `tasks` e `dispatch` retornados por `useReducer()` e [forneça-os](/learn/passing-data-deeply-with-context#step-3-provide-the-context) para toda a árvore abaixo:

```js {4,7-8}
import { TasksContext, TasksDispatchContext } from './TasksContext.js';
Expand All @@ -470,7 +470,7 @@ export default function TaskApp() {
}
```

For now, you pass the information both via props and in context:
Por enquanto, você passa as informações tanto via props quanto em context:

<Sandpack>

Expand Down Expand Up @@ -669,31 +669,31 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

In the next step, you will remove prop passing.
Na próxima etapa, você removerá a passagem de props.

### Step 3: Use context anywhere in the tree {/*step-3-use-context-anywhere-in-the-tree*/}
### Etapa 3: Use o context em qualquer lugar da árvore {/*step-3-use-context-anywhere-in-the-tree*/}

Now you don't need to pass the list of tasks or the event handlers down the tree:
Agora você não precisa passar a lista de tarefas ou os manipuladores de eventos pela árvore:

```js {4-5}
<TasksContext value={tasks}>
<TasksDispatchContext value={dispatch}>
<h1>Day off in Kyoto</h1>
<h1>Dia de folga em Kyoto</h1>
<AddTask />
<TaskList />
</TasksDispatchContext>
</TasksContext>
```

Instead, any component that needs the task list can read it from the `TasksContext`:
Em vez disso, qualquer componente que precise da lista de tarefas pode lê-la do `TasksContext`:

```js {2}
export default function TaskList() {
const tasks = useContext(TasksContext);
// ...
```

To update the task list, any component can read the `dispatch` function from context and call it:
Para atualizar a lista de tarefas, qualquer componente pode ler a função `dispatch` do context e chamá-la:

```js {3,9-13}
export default function AddTask() {
Expand All @@ -709,11 +709,11 @@ export default function AddTask() {
id: nextId++,
text: text,
});
}}>Add</button>
}}>Adicionar</button>
// ...
```

**The `TaskApp` component does not pass any event handlers down, and the `TaskList` does not pass any event handlers to the `Task` component either.** Each component reads the context that it needs:
**O componente `TaskApp` não passa nenhum manipulador de eventos para baixo, e o `TaskList` também não passa nenhum manipulador de eventos para o componente `Task`.** Cada componente lê o context que precisa:

<Sandpack>

Expand All @@ -732,7 +732,7 @@ export default function TaskApp() {
return (
<TasksContext value={tasks}>
<TasksDispatchContext value={dispatch}>
<h1>Day off in Kyoto</h1>
<h1>Dia de folga em Kyoto</h1>
<AddTask />
<TaskList />
</TasksDispatchContext>
Expand Down Expand Up @@ -897,11 +897,11 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

**The state still "lives" in the top-level `TaskApp` component, managed with `useReducer`.** But its `tasks` and `dispatch` are now available to every component below in the tree by importing and using these contexts.
**O estado ainda "vive" no componente `TaskApp` de nível superior, gerenciado com `useReducer`.** Mas seus `tasks` e `dispatch` agora estão disponíveis para todos os componentes abaixo na árvore, importando e usando esses contexts.

## Moving all wiring into a single file {/*moving-all-wiring-into-a-single-file*/}
## Mover toda a lógica de conexão para um único arquivo {/*moving-all-wiring-into-a-single-file*/}

You don't have to do this, but you could further declutter the components by moving both reducer and context into a single file. Currently, `TasksContext.js` contains only two context declarations:
Você não precisa fazer isso, mas pode refinar ainda mais os componentes movendo o reducer e o context para um único arquivo. Atualmente, `TasksContext.js` contém apenas duas declarações de context:

```js
import { createContext } from 'react';
Expand All @@ -910,11 +910,11 @@ export const TasksContext = createContext(null);
export const TasksDispatchContext = createContext(null);
```

This file is about to get crowded! You'll move the reducer into that same file. Then you'll declare a new `TasksProvider` component in the same file. This component will tie all the pieces together:
Este arquivo está prestes a ficar cheio! Você moverá o reducer para esse mesmo arquivo. Em seguida, declarará um novo componente `TasksProvider` no mesmo arquivo. Este componente unirá todas as peças:

1. It will manage the state with a reducer.
2. It will provide both contexts to components below.
3. It will [take `children` as a prop](/learn/passing-props-to-a-component#passing-jsx-as-children) so you can pass JSX to it.
1. Ele gerenciará o estado com um reducer.
2. Ele fornecerá ambos os contexts para os componentes abaixo.
3. Ele [receberá `children` como prop](/learn/passing-props-to-a-component#passing-jsx-as-children) para que você possa passar JSX para ele.

```js
export function TasksProvider({ children }) {
Expand All @@ -930,7 +930,7 @@ export function TasksProvider({ children }) {
}
```

**This removes all the complexity and wiring from your `TaskApp` component:**
**Isso remove toda a complexidade e a lógica de conexão do seu componente `TaskApp`:**

<Sandpack>

Expand Down Expand Up @@ -1121,7 +1121,7 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

You can also export functions that _use_ the context from `TasksContext.js`:
Você também pode exportar funções que _usam_ o context de `TasksContext.js`:

```js
export function useTasks() {
Expand All @@ -1133,14 +1133,14 @@ export function useTasksDispatch() {
}
```

When a component needs to read context, it can do it through these functions:
Quando um componente precisar ler o context, ele poderá fazê-lo através dessas funções:

```js
const tasks = useTasks();
const dispatch = useTasksDispatch();
```

This doesn't change the behavior in any way, but it lets you later split these contexts further or add some logic to these functions. **Now all of the context and reducer wiring is in `TasksContext.js`. This keeps the components clean and uncluttered, focused on what they display rather than where they get the data:**
Isso não altera o comportamento de forma alguma, mas permite que você divida esses contexts posteriormente ou adicione alguma lógica a essas funções. **Agora toda a lógica de context e reducer está em `TasksContext.js`. Isso mantém os componentes limpos e organizados, focados no que exibem em vez de onde obtêm os dados:**

<Sandpack>

Expand Down Expand Up @@ -1340,26 +1340,26 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

You can think of `TasksProvider` as a part of the screen that knows how to deal with tasks, `useTasks` as a way to read them, and `useTasksDispatch` as a way to update them from any component below in the tree.
Você pode pensar em `TasksProvider` como parte da tela que sabe como lidar com tarefas, `useTasks` como uma forma de lê-las e `useTasksDispatch` como uma forma de atualizá-las de qualquer componente abaixo na árvore.

<Note>

Functions like `useTasks` and `useTasksDispatch` are called *[Custom Hooks.](/learn/reusing-logic-with-custom-hooks)* Your function is considered a custom Hook if its name starts with `use`. This lets you use other Hooks, like `useContext`, inside it.
Funções como `useTasks` e `useTasksDispatch` são chamadas de *[Custom Hooks.](/learn/reusing-logic-with-custom-hooks)* Sua função é considerada um custom Hook se o nome dela começar com `use`. Isso permite que você use outros Hooks, como `useContext`, dentro dela.

</Note>

As your app grows, you may have many context-reducer pairs like this. This is a powerful way to scale your app and [lift state up](/learn/sharing-state-between-components) without too much work whenever you want to access the data deep in the tree.
À medida que seu aplicativo cresce, você pode ter muitos pares de context-reducer como este. Esta é uma maneira poderosa de escalar seu aplicativo e [elevar o estado](/learn/sharing-state-between-components) sem muito trabalho sempre que quiser acessar os dados profundamente na árvore.

<Recap>

- You can combine reducer with context to let any component read and update state above it.
- To provide state and the dispatch function to components below:
1. Create two contexts (for state and for dispatch functions).
2. Provide both contexts from the component that uses the reducer.
3. Use either context from components that need to read them.
- You can further declutter the components by moving all wiring into one file.
- You can export a component like `TasksProvider` that provides context.
- You can also export custom Hooks like `useTasks` and `useTasksDispatch` to read it.
- You can have many context-reducer pairs like this in your app.

</Recap>
- Você pode combinar reducer com context para permitir que qualquer componente leia e atualize o estado acima dele.
- Para fornecer o estado e a função de dispatch aos componentes abaixo:
1. Crie dois contexts (para estado e para funções de dispatch).
2. Forneça ambos os contexts do componente que usa o reducer.
3. Use qualquer um dos contexts dos componentes que precisam lê-los.
- Você pode refinar ainda mais os componentes movendo toda a lógica de conexão para um único arquivo.
- Você pode exportar um componente como `TasksProvider` que fornece context.
- Você também pode exportar custom Hooks como `useTasks` e `useTasksDispatch` para lê-lo.
- Você pode ter muitos pares de context-reducer como este em seu aplicativo.

</Recap>
Loading