diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 3e054806a..3fad2b7ff 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -1,6 +1,6 @@ --- id: thinking-in-react -title: Thinking in React +title: Pensando do jeito React permalink: docs/thinking-in-react.html redirect_from: - 'blog/2013/11/05/thinking-in-react.html' @@ -8,17 +8,17 @@ redirect_from: prev: composition-vs-inheritance.html --- -React is, in our opinion, the premier way to build big, fast Web apps with JavaScript. It has scaled very well for us at Facebook and Instagram. +React é, na nossa opinião, o principal modo de se construir aplicações Web grandes e rápidas com JavaScript. Ele tem escalado muito bem para nós no Facebook e Instagram. -One of the many great parts of React is how it makes you think about apps as you build them. In this document, we'll walk you through the thought process of building a searchable product data table using React. +Uma das muitas excelentes partes do React é o modo que ele faz você pensar sobre apps enquanto os constrói. Neste documento, nós iremos ensinar o processo mental envolvido na construção de uma tabela de produtos buscáveis utilizando o React. -## Start With A Mock {#start-with-a-mock} +## Comece Com Um Mock {#start-with-a-mock} -Imagine that we already have a JSON API and a mock from our designer. The mock looks like this: +Imagine que nós tenhamos uma API JSON e um mock desenvolvido pelo nosso designer. O mock se parece com isso: ![Mockup](../images/blog/thinking-in-react-mock.png) -Our JSON API returns some data that looks like this: +Nossa API JSON retorna dados como esses: ``` [ @@ -31,27 +31,27 @@ Our JSON API returns some data that looks like this: ]; ``` -## Step 1: Break The UI Into A Component Hierarchy {#step-1-break-the-ui-into-a-component-hierarchy} +## Passo 1: Separe a UI Em Uma Hierarquia De Componentes{#step-1-break-the-ui-into-a-component-hierarchy} -The first thing you'll want to do is to draw boxes around every component (and subcomponent) in the mock and give them all names. If you're working with a designer, they may have already done this, so go talk to them! Their Photoshop layer names may end up being the names of your React components! +A primeira coisa que você vai querer fazer é dar nomes e desenhar retângulos em volta de cada componente (e subcomponente) do mock. Se você estiver trabalhando com designers, eles podem já ter feito isso, então vá falar com eles! Os nomes das camadas no Photoshop podem acabar sendo os nomes dos seus componentes React! -But how do you know what should be its own component? Just use the same techniques for deciding if you should create a new function or object. One such technique is the [single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle), that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents. +Mas como você sabe o que deveria ser seu próprio componente? Simplesmente use as mesmas técnicas que você usaria para decidir se você deveria criar uma nova função ou objeto. Uma dessas técnicas é o [princípio da responsabilidade única](https://en.wikipedia.org/wiki/Single_responsibility_principle), ou seja, um componente deve idealmente fazer apenas uma coisa. Se ele acabar crescendo, deverá ser decomposto em subcomponentes menores. -Since you're often displaying a JSON data model to a user, you'll find that if your model was built correctly, your UI (and therefore your component structure) will map nicely. That's because UI and data models tend to adhere to the same *information architecture*, which means the work of separating your UI into components is often trivial. Just break it up into components that represent exactly one piece of your data model. +Visto que você estará frequentemente exibindo um modelo de dados em JSON ao usuário, você perceberá que caso o seu modelo esteja corretamente construído, sua UI (e portanto a sua estrutura de componente) será mapeada satisfatoriamente. Isso acontece pois UI e modelo de dados tendem a aderir à mesma *arquitetura de informação*, o que significa que o trabalho de separar a UI em componentes é muitas vezes trivial. Apenas separe em componentes o que representa exatamente um pedaço do seu modelo de dados. -![Component diagram](../images/blog/thinking-in-react-components.png) +![Diagrama de componentes](../images/blog/thinking-in-react-components.png) -You'll see here that we have five components in our simple app. We've italicized the data each component represents. +Você verá que nós temos cinco componentes nessa simples aplicação. Em itálico estão os dados que cada componente representa. - 1. **`FilterableProductTable` (orange):** contains the entirety of the example - 2. **`SearchBar` (blue):** receives all *user input* - 3. **`ProductTable` (green):** displays and filters the *data collection* based on *user input* - 4. **`ProductCategoryRow` (turquoise):** displays a heading for each *category* - 5. **`ProductRow` (red):** displays a row for each *product* + 1. **`FilterableProductTable` (laranja):** contém a totalidade do exemplo + 2. **`SearchBar` (azul):** recebe todo *input do usuário* + 3. **`ProductTable` (verde):** exibe e filtra a *coleção de dados* baseado no *input do usuário* + 4. **`ProductCategoryRow` (turquesa):** exibe um cabeçalho para cada *categoria* + 5. **`ProductRow` (vermelho):** exibe uma linha para cada *produto* -If you look at `ProductTable`, you'll see that the table header (containing the "Name" and "Price" labels) isn't its own component. This is a matter of preference, and there's an argument to be made either way. For this example, we left it as part of `ProductTable` because it is part of rendering the *data collection* which is `ProductTable`'s responsibility. However, if this header grows to be complex (i.e. if we were to add affordances for sorting), it would certainly make sense to make this its own `ProductTableHeader` component. +Se você olhar para `ProductTable`, verá que o cabeçalho da tabela (contendo as etiquetas "Name" and "Price") não é um componente separado. Isso é uma questão de preferência, e pode-se fazer um argumento contrário. Para esse exemplo, nós o deixamos como parte de `ProductTable` pois o cabeçalho faz parte da renderização da *coleção de dados*, que é responsabilidade de `ProductTable`. Entretanto, se a sua complexidade aumentar (i.e. se nós adicionássemos a capacidade de ordenação), certamente faria sentido a criação do componente `ProductTableHeader`. -Now that we've identified the components in our mock, let's arrange them into a hierarchy. This is easy. Components that appear within another component in the mock should appear as a child in the hierarchy: +Agora que nós já identificamos os componentes do nosso mock, vamos organizá-los em uma hierarquia. Isso é fácil. Componentes que aparecem dentro de outros no mock devem aparecer como filhos na hierarquia: * `FilterableProductTable` * `SearchBar` @@ -59,90 +59,90 @@ Now that we've identified the components in our mock, let's arrange them into a * `ProductCategoryRow` * `ProductRow` -## Step 2: Build A Static Version in React {#step-2-build-a-static-version-in-react} +## Passo 2: Crie Uma Versão Estática Em React {#step-2-build-a-static-version-in-react} -

See the Pen Thinking In React: Step 2 on CodePen.

+

Veja o Pen Pensando em React: Passo 2 no CodePen.

-Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why. +Agora que você já tem sua hierarquia de componentes, chegou a hora de implementar o seu app. O modo mais fácil é construir uma versão que recebe o seu modelo de dados e renderiza a UI, mas sem interatividade. É melhor desacoplar esses processos uma vez que criar uma versão estática requer muita digitação e pouco pensamento, enquanto adicionar interatividade requer muito pensamento e pouca digitação. Nós veremos o porquê. -To build a static version of your app that renders your data model, you'll want to build components that reuse other components and pass data using *props*. *props* are a way of passing data from parent to child. If you're familiar with the concept of *state*, **don't use state at all** to build this static version. State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app, you don't need it. +Para construir uma versão estática que renderiza seu modelo de dados, você quer criar componentes que reutilizem outros componentes e passem dados utilizando *props*. *props* são uma forma de passar dados de pai para filho. Se você é familiar com o conceito de *state* (estado), **não use o state** para construir essa versão estática. State é reservado apenas para interatividade, ou seja, dados que mudam com o tempo. Uma vez que essa é uma versão estática do app, seu uso não será necessário. -You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with `FilterableProductTable`) or with the ones lower in it (`ProductRow`). In simpler examples, it's usually easier to go top-down, and on larger projects, it's easier to go bottom-up and write tests as you build. +Você pode seguir uma abordagem cima-para-baixo ou baixo-para-cima. Isso significa que você pode começar criando os componentes no topo da hierarquia (i.e. começar com `FilterableProductTable`) ou os da base (`ProductRow`). Em exemplos simples, cima-para-baixo é normalmente mais fácil, enquanto que para projetos maiores o melhor é usar uma estratégia baixo-para-cima e escrever testes à medida que você for avançando. -At the end of this step, you'll have a library of reusable components that render your data model. The components will only have `render()` methods since this is a static version of your app. The component at the top of the hierarchy (`FilterableProductTable`) will take your data model as a prop. If you make a change to your underlying data model and call `ReactDOM.render()` again, the UI will be updated. It's easy to see how your UI is updated and where to make changes since there's nothing complicated going on. React's **one-way data flow** (also called *one-way binding*) keeps everything modular and fast. +No final dessa etapa, você terá uma biblioteca de componentes reutilizáveis que renderizam seu modelo de dados. Seus componentes terão apenas o método `render()` uma vez que é apenas uma versão estática do seu app. O componente no topo da hierarquia (`FilterableProductTable`) receberá o modelo de dados como uma prop. Se você fizer alguma alteração no seu modelo de dados e chamar `ReactDOM.render()` novamente, a UI será atualizada. É fácil entender como sua UI é atualizada e onde realizar as alterações uma vez que não há nada de mais complicado acontecendo. O **fluxo de dados unidirecional** (_one-way data flow_) do React (também chamado de **ligação unidirecional** _ou one-way binding_) mantém tudo rápido e modular. -Simply refer to the [React docs](/docs/) if you need help executing this step. +Recorra à [documentação do React](/docs/) caso você precise de ajuda para executar esse passo. -### A Brief Interlude: Props vs State {#a-brief-interlude-props-vs-state} +### Um Breve Interlúdio: Props vs State {#a-brief-interlude-props-vs-state} -There are two types of "model" data in React: props and state. It's important to understand the distinction between the two; skim [the official React docs](/docs/interactivity-and-dynamic-uis.html) if you aren't sure what the difference is. +Existem dois tipos de "modelo" de dados em React: props e state. É de suma importância entender a distinção entre os dois; dê uma olhada na [documentação oficial do React](/docs/interactivity-and-dynamic-uis.html) caso você ainda não esteja certo da diferença. -## Step 3: Identify The Minimal (but complete) Representation Of UI State {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} +## Passo 3: Identifique a Representação Mínima (mas completa) do State da UI{#step-3-identify-the-minimal-but-complete-representation-of-ui-state} -To make your UI interactive, you need to be able to trigger changes to your underlying data model. React makes this easy with **state**. +Para tornar sua UI interativa, você precisa poder desencadear mudanças no seu modelo de dados. React torna isso fácil com **state**. -To build your app correctly, you first need to think of the minimal set of mutable state that your app needs. The key here is [DRY: *Don't Repeat Yourself*](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). Figure out the absolute minimal representation of the state your application needs and compute everything else you need on-demand. For example, if you're building a TODO list, just keep an array of the TODO items around; don't keep a separate state variable for the count. Instead, when you want to render the TODO count, simply take the length of the TODO items array. +Para construir seu app corretamente, você primeiro deve pensar no conjunto mínimo de estados mutáveis que ele precisa. A chave aqui é [DRY: *Don't Repeat Yourself*](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) (_Não repita a si mesmo_). Descubra a representação mínima do state que a sua aplicação precisa e compute todo o resto sob demanda. Por exemplo, se você está criando uma lista de afazeres, simplesmente mantenha um array com cada item a ser feito; não tenha uma variável de state separada para a contagem. Ao contrário, quando você quiser renderizar a quantidade de afazeres, simplesmente calcule o comprimento do array. -Think of all of the pieces of data in our example application. We have: +Pense em todos os pedaços de dados do nosso exemplo. Nós temos: - * The original list of products - * The search text the user has entered - * The value of the checkbox - * The filtered list of products + * A lista original de produtos + * O texto de busca que o usuário digitou + * O valor do checkbox + * A lista filtrada de produtos -Let's go through each one and figure out which one is state. Simply ask three questions about each piece of data: +Vamos analisar um a um e descobrir quais fazem parte do state. Simplesmente faça três perguntas para cada pedaço de dado: - 1. Is it passed in from a parent via props? If so, it probably isn't state. - 2. Does it remain unchanged over time? If so, it probably isn't state. - 3. Can you compute it based on any other state or props in your component? If so, it isn't state. + 1. Ele é recebido pelo pai via props? Se sim, provavelmente não é state. + 2. Ele se mantém inalterado ao longo do tempo? Se sim, provavelmente não é state. + 3. Ele pode ser computado através de qualquer outro state ou props do seu componente? Se sim, não é state. -The original list of products is passed in as props, so that's not state. The search text and the checkbox seem to be state since they change over time and can't be computed from anything. And finally, the filtered list of products isn't state because it can be computed by combining the original list of products with the search text and value of the checkbox. +A lista original de produtos é passada via props, então não é state. O texto de busca e o checkbox parecem ser state uma vez que eles mudam com o tempo e não podem ser computados por qualquer outro valor. Finalmente, a lista filtrada de produtos não é state pois pode ser computada ao se combinar a lista original com o texto de busca e o valor do checkbox. -So finally, our state is: +Então, finalmente, nosso state é: - * The search text the user has entered - * The value of the checkbox + * O texto de busca que o usuário digitou + * O valor do checkbox -## Step 4: Identify Where Your State Should Live {#step-4-identify-where-your-state-should-live} +## Passo 4: Identifique Onde o State Deve Ficar{#step-4-identify-where-your-state-should-live} -

See the Pen Thinking In React: Step 4 on CodePen.

+

Veja o Pen Pensando em React: Passo 4 no CodePen.

-OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or *owns*, this state. +OK, então nós já identificamos qual é o menor conjunto para o state da aplicação. Em seguida, nós precisamos identificar quais componentes são mutáveis, ou *possuem* esse state. -Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. **This is often the most challenging part for newcomers to understand,** so follow these steps to figure it out: +Lembre-se: React é todo sobre fluxo de dados unidirecional através da hierarquia de componentes. Pode não ser imediatamente claro qual componente deve possuir o estado. **Isso é muitas vezes a parte mais desafiadora para os iniciantes entenderem,** então siga esses passos para descobrir: -For each piece of state in your application: +Para cada pedaço do estado da sua aplicação: - * Identify every component that renders something based on that state. - * Find a common owner component (a single component above all the components that need the state in the hierarchy). - * Either the common owner or another component higher up in the hierarchy should own the state. - * If you can't find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component. + * Identifique todo componente que renderiza alguma coisa baseado no state. + * Ache um componente-pai comum (um único componente acima dos outros na hierarquia que necessita do state). + * O componente-pai comum ou algum outro acima na hierarquia deve possuir o state. + * Caso você não consiga achar algum componente em que a posse do state faça sentido, crie um componente com o único propósito de manter o state e o adicione em algum lugar da hierarquia acima do componente-pai. -Let's run through this strategy for our application: +Vamos testar essa estratégia no nosso exemplo: - * `ProductTable` needs to filter the product list based on state and `SearchBar` needs to display the search text and checked state. - * The common owner component is `FilterableProductTable`. - * It conceptually makes sense for the filter text and checked value to live in `FilterableProductTable` + * `ProductTable` precisa filtrar a lista de produtos baseado no state e `SearchBar` precisa exibir o texto de busca e o estado do checkbox. + * O componente-pai comum é `FilterableProductTable`. + * Conceitualmente faz mais sentido que o texto de busca e o valor do checkbox fiquem em `FilterableProductTable`. -Cool, so we've decided that our state lives in `FilterableProductTable`. First, add an instance property `this.state = {filterText: '', inStockOnly: false}` to `FilterableProductTable`'s `constructor` to reflect the initial state of your application. Then, pass `filterText` and `inStockOnly` to `ProductTable` and `SearchBar` as a prop. Finally, use these props to filter the rows in `ProductTable` and set the values of the form fields in `SearchBar`. +Legal, então nós decidimos que nosso state fica em `FilterableProductTable`. Primeiro, adicione a propriedade `this.state = {filterText: '', inStockOnly: false}` ao `constructor` de `FilterableProductTable` de modo a refletir o estado inicial da aplicação. Então, passe `filterText` e `inStockOnly` para `ProductTable` e `SearchBar` como uma prop. Finalmente, use essas props para filtrar as linhas em `ProductTable` e preencha os valores dos campos do formulário em `SearchBar`. -You can start seeing how your application will behave: set `filterText` to `"ball"` and refresh your app. You'll see that the data table is updated correctly. +Você começará a ver como a aplicação vai se comportar: assinale o valor de `filterText` para `"ball"` e atualize seu app. Você verá que a tabela é atualizada corretamente. -## Step 5: Add Inverse Data Flow {#step-5-add-inverse-data-flow} +## Passo 5: Adicione o Fluxo de Dados Inverso {#step-5-add-inverse-data-flow} -

See the Pen Thinking In React: Step 5 on CodePen.

+

Veja o Pen Pensando em React: Passo 5 no CodePen.

-So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`. +Até aqui nós construímos um app que comporta-se como uma função das props e state que fluem através da hierarquia. Agora é hora de suportar o fluxo no outro sentido: os elementos de formulário na base da hierarquia precisam atualizar o state em `FilterableProductTable`. -React makes this data flow explicit to make it easy to understand how your program works, but it does require a little more typing than traditional two-way data binding. +React torna explícito esse tipo de fluxo de modo a facilitar o entendimento de como o seu programa funciona, mas isso requer um pouco mais de digitação que o a ligação bi-direcional de dados (two-way data binding) tradicional. -If you try to type or check the box in the current version of the example, you'll see that React ignores your input. This is intentional, as we've set the `value` prop of the `input` to always be equal to the `state` passed in from `FilterableProductTable`. +Se você tentar escrever ou marcar o checkbox na versão atual do nosso exemplo, perceberá que o React ignorará o seu input. Isso é intencional, uma vez que nós estabelecemos que a prop `value` do input deve ser sempre igual ao `state` passado por `FilterableProductTable`. -Let's think about what we want to happen. We want to make sure that whenever the user changes the form, we update the state to reflect the user input. Since components should only update their own state, `FilterableProductTable` will pass callbacks to `SearchBar` that will fire whenever the state should be updated. We can use the `onChange` event on the inputs to be notified of it. The callbacks passed by `FilterableProductTable` will call `setState()`, and the app will be updated. +Vamos pensar um pouco sobre o que nós queremos que aconteça. Queremos ter certeza que sempre que o usuário modificar o formulário o state é atualizado para refletir o input. Uma vez que componentes devem atualizar apenas o seu próprio state, `FilterableProductTable` passará para `SearchBar` callbacks que deverão ser acionados sempre que o state precisar ser alterado. Nós podemos usar o evento `onChange` dos inputs para sermos notificados sobre isso. Os callbacks passados por `FilterableProductTable` irão chamar `setState()` e o app será atualizado. -Though this sounds complex, it's really just a few lines of code. And it's really explicit how your data is flowing throughout the app. +Embora pareça complexo, é realmente uma questão de poucas linhas de código. E torna realmente explícito o fluxo de dados através do seu app. -## And That's It {#and-thats-it} +## E É Isso {#and-thats-it} -Hopefully, this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you're used to, remember that code is read far more than it's written, and it's extremely easy to read this modular, explicit code. As you start to build large libraries of components, you'll appreciate this explicitness and modularity, and with code reuse, your lines of code will start to shrink. :) +Com sorte, esse artigo lhe dará uma ideia de como pensar ao se construir aplicações com React. Embora possa ter um pouco mais de digitação do que você esteja acostumado, lembre-se que códigos são lidos muito mais que escritos, e é extremamente fácil de ler um código explícito e modular. À medida que você começar a criar grandes bibliotecas de componentes, você apreciará essa clareza e modularidade, e com o reuso de código, suas linhas de código começarão a diminuir. :)