<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Filipe Virgínio Vital Torres Barbosa - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Filipe Virgínio Vital Torres Barbosa - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 19 Jun 2026 05:19:25 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/author/filipe-torres/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Ficha informativa de React com exemplos reais ]]>
                </title>
                <description>
                    <![CDATA[ Elaborei uma ficha informativa visual e abrangente para ajudá-lo a dominar todos os principais conceitos e recursos da biblioteca do React. > Nota da tradução: este texto foi escrito em 2021. Nos últimos três anos, algumas modificações do React podem ter tornado diversas partes deste artigo obsoletas. Criei esta ficha ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/ficha-informativa-de-react-com-exemplos-reais/</link>
                <guid isPermaLink="false">667721c279dc5c03cfad5133</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Filipe Virgínio Vital Torres Barbosa ]]>
                </dc:creator>
                <pubDate>Wed, 02 Apr 2025 00:57:08 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/12/the-react-cheatsheet-for-2021-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">The React Cheatsheet for 2021‬ (+ Real-World Examples)</a>
      </p><p>Elaborei uma ficha informativa visual e abrangente para ajudá-lo a dominar todos os principais conceitos e recursos da biblioteca do React.</p><blockquote>Nota da tradução: este texto foi escrito em 2021. Nos últimos três anos, algumas modificações do React podem ter tornado diversas partes deste artigo obsoletas.</blockquote><p><strong><strong>Criei es</strong>t<strong>a f</strong>icha informativa <strong>para ajudá-lo a otimizar seu aprendizado de React no menor tempo possível.</strong></strong></p><p>Ela inclui vários exemplos práticos para ilustrar cada recurso da biblioteca e como ela funciona usando padrões que você pode aplicar em seus próprios projetos.</p><p>Junto com cada trecho de código, adicionei muitos comentários úteis. Se você ler esses comentários, verá o que cada linha de código faz, como os diferentes conceitos se relacionam entre si e obterá um entendimento mais completo de como o React pode ser usado.</p><p>Observe que as palavras-chave particularmente úteis para você conhecer como desenvolvedor do React estão destacadas em negrito. Portanto, fique atento a elas.</p><ul><li>Guia de referência rápida para revisar quando e como quiser</li><li>Inúmeros de trechos de código copiáveis para facilitar a reutilização</li><li>Leia este enorme guia onde for melhor para você. No trem, na sua mesa, na fila... em qualquer lugar.</li></ul><p>Há muitas coisas ótimas para tratarmos. Então, vamos começar.</p><blockquote>Deseja executar qualquer um dos trechos de código abaixo? Crie uma aplicação em React para experimentar qualquer um desses exemplos usando a ferramenta on-line (gratuita) CodeSandbox. Você pode fazer isso instantaneamente visitando <a href="https://react.new/">react.new</a>.</blockquote><h2 id="sum-rio"><strong>Sumário</strong></h2><h3 id="fundamentos-do-react"><strong>Fundamentos do React</strong></h3><ul><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#jsx-elements">Elementos JSX</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#components-and-props">Componentes e <em>props</em></a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#lists-and-keys">Listas e chaves</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#event-listeners-and-handling-events">Ouvintes de eventos e tratamento de eventos</a></li></ul><h3 id="hooks-essenciais-do-react"><strong>Hooks essenciais do React</strong></h3><ul><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#state-and-usestate">State e useState</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#side-effects-and-useeffect">Efeitos colaterais e useEffect</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#refs-and-useref">Refs e useRef</a></li></ul><h3 id="hooks-e-desempenho"><strong>Hooks e desempenho</strong></h3><ul><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#preventing-re-renders-and-react-memo">Prevenção de novas renderizações e React.memo</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#callback-functions-and-usecallback">Funções de <em>callback</em> e useCallback</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#memoization-and-usememo">Memoização e useMemo</a></li></ul><h3 id="hooks-avan-ados-do-react"><strong>Hooks avançados do React</strong></h3><ul><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#context-and-usecontext">Contexto e useContext</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#reducers-and-usereducer">Redutores e useReducer</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#writing-custom-hooks">Escrevendo hooks personalizados</a></li><li><a href="https://www.freecodecamp.org/news/react-cheatsheet-with-real-world-examples/#rules-of-hooks">Regras de hooks</a></li></ul><h2 id="fundamentos-do-react-1"><strong>Fundamentos do React</strong></h2><h3 id="elementos-jsx"><strong>Elementos JSX</strong></h3><p>As aplicações em React são estruturadas usando uma sintaxe chamada <strong><strong>JSX</strong></strong>. Esta é a sintaxe de um <strong><strong>elemento JSX</strong></strong> básico.</p><pre><code class="language-js">/* 
  O JSX nos permite escrever em uma sintaxe quase idêntica à do HTML simples.
  O resultado disso é que o JSX é uma ferramenta poderosa para estruturar nossas aplicações.
  O JSX usa todas as tags HTML válidas (ou seja, div/span, h1-h6, form/input, img etc.).
*/

&lt;div&gt;Alô, React!&lt;/div&gt;

/* 
  Observação: esse JSX não seria visível porque precisa ser renderizado por nossa aplicação usando ReactDOM.render()
*/</code></pre><p>O JSX é a maneira mais comum de estruturar aplicações em React, mas não é obrigatório para o React.</p><pre><code class="language-js">/* O JSX é uma maneira mais simples de usar a função React.createElement()
Em outras palavras, as duas linhas a seguir no React são iguais: */

&lt;div&gt;Alô, React!&lt;/div&gt;  // sintaxe do JSX

React.createElement('div', null, 'Alô, React!'); // sintaxe do createElement</code></pre><p>O JSX não é compreendido pelo navegador. Ele precisa ser compilado em JavaScript puro para que o navegador possa entender.</p><p>O compilador mais comumente usado para JSX é chamado Babel.</p><pre><code class="language-js">/* 
  Quando nosso projeto é criado para ser executado no navegador, nosso JSX será convertido pelo Babel em chamadas simples da função React.createElement(). 
  Disto...
*/
const greeting = &lt;div&gt;Alô React!&lt;/div&gt;;

/* ...para isto: */
"use strict";

const greeting = /*#__PURE__*/React.createElement("div", null, "Alô, React!");</code></pre><p>O JSX difere do HTML de várias maneiras importantes:</p><pre><code class="language-js">/* 
  Podemos escrever JSX como se fosse HTML simples, mas na verdade ele é feito usando funções JavaScript.
  Como o JSX é JavaScript, e não HTML, há algumas diferenças:

  1) Alguns atributos JSX têm nomes diferentes dos atributos HTML. Por quê? Porque algumas palavras de atributos são palavras reservadas em JavaScript, como 'class' (classe). Em vez de class, o JSX usa 'className'.

  Além disso, como o JSX é JavaScript, os atributos que consistem em várias palavras são escritos em camelcase:
*/

&lt;div id="header"&gt;
  &lt;h1 className="title"&gt;Alô, React!&lt;/h1&gt;
&lt;/div&gt;

/* 
  2) Os elementos JSX que consistem em apenas uma única tag (ou seja, elementos input, img, br) devem ser fechados com uma barra à direita para serem válidos (/): 
*/

&lt;input type="email" /&gt; // &lt;input type="email"&gt; é um erro de sintaxe

/* 
  3) Os elementos JSX que consistem em uma tag de abertura e de fechamento (ou seja, div, span, elemento de botão) devem ter ambas ou ser fechados com uma barra à direita. Como no item 2) acima, é um erro de sintaxe ter um elemento não encerrado. 
*/

&lt;button&gt;Clique aqui&lt;/button&gt; // somente &lt;button&gt; ou &lt;/button&gt; geram um erro de sintaxe
&lt;button /&gt; // vazio, mas também válido</code></pre><p>Estilos em linha podem ser adicionados aos elementos JSX usando o atributo <code>style</code>. Os estilos são atualizados em um objeto, e não em um conjunto de aspas duplas, como no HTML.</p><p>Observe que os nomes das propriedades de estilo também devem ser escritos em <em>camelcase</em>.</p><pre><code class="language-js">/* 
  As propriedades que aceitam valores de pixel (como largura, altura, preenchimento, margem etc.) podem usar números inteiros em vez de cadeias de caracteres.
  Por exemplo: fontSize: 22. Em vez de: fontSize: "22px"
*/
&lt;h1 style={{ color: 'blue', fontSize: 22, padding: '0.5em 1em' }}&gt;
  Alô, React!
&lt;/h1&gt;</code></pre><p>Os elementos JSX são expressões JavaScript e podem ser usados como tal. O JSX nos dá todo o poder do JavaScript diretamente em nossa interface de usuário.</p><pre><code class="language-js">/* 
  Os elementos JSX são expressões (resultam em um valor) e, portanto, podem ser atribuídos a variáveis JavaScript simples... 
*/
const greeting = &lt;div&gt;Alô, React!&lt;/div&gt;;

const isNewToReact = true;

// ... ou pode ser exibido condicionalmente
function sayGreeting() {
  if (isNewToReact) {
    // ... ou retornado de funções, etc.
    return greeting; // exibe: Alô, React!
  } else {
    return &lt;div&gt;Olá novamente, React&lt;/div&gt;;
  }
}</code></pre><p>O JSX nos permite inserir (ou incorporar) expressões JavaScript simples usando a sintaxe de chaves:</p><pre><code class="language-js">const year = 2021;

/* Podemos inserir valores JS primitivos (ou seja, strings, números, booleanos) entre chaves: {} */
const greeting = &lt;div&gt;Alô, React, em {year}&lt;/div&gt;;

/* Também podemos inserir expressões que resultam em um valor primitivo: */
const goodbye = &lt;div&gt;Adeus ano velho: {year - 1}&lt;/div&gt;

/* As expressões também podem ser usadas para atributos de elementos */
const className = 'title';
const title = &lt;h1 className={className}&gt;Meu título&lt;/h1&gt;

/* Observação: tentar inserir valores de objetos (por exemplo: objetos, arrays, maps) entre chaves resultará em um erro */</code></pre><p>O JSX nos permite aninhar elementos uns nos outros, como faríamos com o HTML.</p><pre><code class="language-js">/* 
  Para escrever JSX em várias linhas, coloque entre parênteses: ()
  As expressões JSX que abrangem várias linhas são chamadas de expressões multilinhas
*/

const greeting = (
  // div é o elemento pai
  &lt;div&gt;
    {/* h1 e p são elementos filhos */}
    &lt;h1&gt;Alô!&lt;/h1&gt;
    &lt;p&gt;Bem vindo ao React&lt;/p&gt;
  &lt;/div&gt;
);
/* 'pais' e 'filhos' são a forma como descrevemos os elementos JSX em relação
uns com os outros, como se estivéssemos falando de elementos HTML */</code></pre><p>Os comentários em JSX são escritos como comentários JavaScript de várias linhas, escritos entre chaves, como este:</p><pre><code class="language-js">const greeting = (
  &lt;div&gt;
    {/* Este é um comentário de uma única linha */}
  	&lt;h1&gt;Alô!&lt;/h1&gt;
    	&lt;p&gt;Bem vindo ao React&lt;/p&gt;
    {/* Este é 
    	um comentário
        de várias linhas */} 
  &lt;/div&gt;
);</code></pre><p>Todas as aplicações em React exigem três coisas:</p><ol><li><code>ReactDOM.render()</code>: usado para renderizar (exibir) nossa aplicação, montando-a em um elemento HTML</li><li>Um elemento JSX: chamado de "nó raiz", porque é a raiz da nossa aplicação. Em outras palavras, ao renderizá-lo, renderizará também todos os filhos dentro dele</li><li>Um elemento HTML (DOM): onde a aplicação é inserida em uma página HTML. O elemento geralmente é uma div com um id de valor "root", localizado em um arquivo index.html.</li></ol><pre><code class="language-js">// Os pacotes podem ser instalados localmente ou trazidos por meio de um link de um CDN (adicionado ao cabeçalho do documento HTML)
import React from "react";
import ReactDOM from "react-dom";

// O nó raiz (geralmente um componente) é mais frequentemente chamado de "App"
const App = &lt;h1&gt;Alô, React!&lt;/h1&gt;;

// ReactDOM.render(nó raiz, elemento HTML)
ReactDOM.render(App, document.getElementById("root"));</code></pre><h3 id="componentes-e-props"><strong>Componentes e <em>props</em></strong></h3><p>O JSX pode ser agrupado em funções individuais chamadas <strong><strong>componentes</strong></strong>.</p><p>Há dois tipos de componentes no React: <strong><strong>componentes de função</strong></strong> e <strong><strong>componentes de classe</strong></strong>.</p><p>Os nomes de componentes, sejam para componentes de função ou de classe, são capitalizados para distingui-los das funções JavaScript simples que não retornam JSX:</p><pre><code class="language-js">import React from "react";

/* 	
  Componente de função
  Observe o nome da função capitalizado: 'Header', e não 'header'
*/
function Header() {
  return &lt;h1&gt;Alô, React&lt;/h1&gt;;
}

// Os componentes de função que usam uma sintaxe de arrow function também são válidos
const Header = () =&gt; &lt;h1&gt;Alô, React&lt;/h1&gt;;

/* 
  Componente de classe
  Os componentes de classe têm mais boilerplate (observe a palavra-chave 'extends' e o método 'render'.)
*/
class Header extends React.Component {
  render() {
    return &lt;h1&gt;Alô, React&lt;/h1&gt;;
  }
}</code></pre><p>Os componentes, apesar de serem funções, não são chamados como funções JavaScript comuns. Eles são executados ao renderizá-los como faríamos com o JSX em nossa aplicação.</p><pre><code class="language-js">// Chamamos esse componente de função como uma função normal?

// Não, para executá-las e exibir o JSX que elas retornam...
const Header = () =&gt; &lt;h1&gt;Alô, React&lt;/h1&gt;;

// ...usamos como elementos JSX 'personalizados'.
ReactDOM.render(&lt;Header /&gt;, document.getElementById("root"));
// renderiza: &lt;h1&gt;Alô, React&lt;/h1&gt;</code></pre><p>A grande vantagem dos componentes é sua capacidade de serem reutilizados em todas as aplicações, sempre que necessário.</p><p>Como os componentes aproveitam o poder das funções JavaScript, podemos passar dados logicamente para eles, como faríamos ao passar um ou mais argumentos.</p><pre><code class="language-js">/* 
  Os componentes Header e Footer podem ser reutilizados em qualquer página da nossa aplicação.
  Os componentes eliminam a necessidade de reescrever o mesmo JSX várias vezes.
*/

// Componente IndexPage, visível na rota '/' de nosso aplicativo
function IndexPage() {
  return (
    &lt;div&gt;
      &lt;Header /&gt;
      &lt;Hero /&gt;
      &lt;Footer /&gt;
    &lt;/div&gt;
  );
}

// Componente AboutPage, visível na rota '/about'.
function AboutPage() {
  return (
    &lt;div&gt;
      &lt;Header /&gt;
      &lt;About /&gt;
      &lt;Testimonials /&gt;
      &lt;Footer /&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Os dados passados aos componentes em JavaScript são chamados de <strong><strong>props</strong></strong>. As <em>props</em> são idênticas aos atributos dos elementos JSX/HTML simples, mas você pode acessar seus valores dentro do próprio componente.</p><p><em>Props</em> estão disponíveis nos parâmetros do componente para o qual são passadas. <em>Props</em> são sempre incluídas como propriedades de um objeto.</p><pre><code class="language-js">/* 
  O que fazemos se quisermos passar dados personalizados para o nosso componente a partir de um componente pai?
  Por exemplo, para exibir o nome do usuário no cabeçalho da aplicação.
*/

const username = "John";

/* 
  Para isso, adicionamos 'atributos' personalizados ao nosso componente, chamados props.
  Podemos adicionar muitos deles como quisermos e dar a eles nomes adequados aos dados que passamos.
Para passar o nome do usuário para o cabeçalho, usamos uma prop que chamamos apropriadamente de 'username'
*/
ReactDOM.render(
  &lt;Header username={username} /&gt;,
  document.getElementById("root")
);
// Chamamos essa prop de 'username', mas podemos usar qualquer identificador válido que daríamos, por exemplo, uma variável JavaScript

// props é o objeto que cada componente recebe como argumento
function Header(props) {
  // as props que criamos no componente (username)
  // se tornam propriedades no objeto props
  return &lt;h1&gt;Hello {props.username}&lt;/h1&gt;;
}</code></pre><p>As props nunca devem ser alteradas diretamente no componente filho.</p><p>Outra maneira de dizer isso é que as props nunca devem sofrer <strong><strong>mutação</strong></strong>, pois são um objeto JavaScript simples.</p><pre><code class="language-js">/* 
  Os componentes devem operar como funções 'puras'.
  Ou seja, para cada entrada, devemos poder esperar o mesmo resultado.
  Isso significa que não podemos alterar o objeto props, apenas ler a partir dele.
*/

// Não podemos modificar o objeto props :
function Header(props) {
  props.username = "Doug";

  return &lt;h1&gt;Hello {props.username}&lt;/h1&gt;;
}
/* 
  O que faríamos se quiséssemos modificar um valor de prop que é passado para o nosso componente?
  É nesse caso que usaríamos o state (consulte a seção useState).
*/</code></pre><p>A prop de <strong><strong>filhos</strong></strong> é útil se quisermos passar elementos/componentes como props para outros componentes.</p><pre><code class="language-js">// Podemos aceitar elementos (ou componentes) React como props?
// Sim, por meio de uma propriedade especial no objeto props chamada 'children'

function Layout(props) {
  return &lt;div className="container"&gt;{props.children}&lt;/div&gt;;
}

// A propriedade children é muito útil para quando você deseja que o mesmo
// componente (como um componente Layout) para envolver todos os outros componentes:
function IndexPage() {
  return (
    &lt;Layout&gt;
      &lt;Header /&gt;
      &lt;Hero /&gt;
      &lt;Footer /&gt;
    &lt;/Layout&gt;
  );
}

// página diferente, mas usa o mesmo componente Layout (graças à prop children)
function AboutPage() {
  return (
    &lt;Layout&gt;
      &lt;About /&gt;
      &lt;Footer /&gt;
    &lt;/Layout&gt;
  );
}</code></pre><p>Mais uma vez, como os componentes são expressões JavaScript, podemos usá-los em combinação com instruções <em>if-else</em> e <em>switch</em> para exibir conteúdo de modo condicional, como neste exemplo:</p><pre><code class="language-js">function Header() {
  const isAuthenticated = checkAuth();
    
  /* se o usuário estiver autenticado, mostrar a aplicação autenticada; caso contrário, a aplicação não autenticado */
  if (isAuthenticated) {
    return &lt;AuthenticatedApp /&gt;   
  } else {
    /* Como alternativa, podemos eliminar a seção else e fornecer um simples retorno, e a condicional funcionará da mesma maneira */
    return &lt;UnAuthenticatedApp /&gt;   
  }
}</code></pre><p>Para usar condições no JSX retornado de um componente, você pode usar o operador ternário ou o curto-circuito (operadores &amp;&amp; e ||).</p><pre><code class="language-js">function Header() {
  const isAuthenticated = checkAuth();

  return (
    &lt;nav&gt;
      {/* Se isAuth for verdadeiro, não mostrará nada. Se for falso, mostre Logo  */}
      {isAuthenticated || &lt;Logo /&gt;}
      {/* Se isAuth for verdadeiro, exibirá AuthenticatedApp. Se for falso, exibirá Login  */}
      {isAuthenticated ? &lt;AuthenticatedApp /&gt; : &lt;LoginScreen /&gt;}
      {/* Se isAuth for verdadeiro, exibirá o Footer. Se for falso, não mostrará nada */}
      {isAuthenticated &amp;&amp; &lt;Footer /&gt;}
    &lt;/nav&gt;
  );
}</code></pre><p><em><strong>F<strong>ragments</strong></strong> </em>são componentes especiais para exibir vários componentes sem adicionar um elemento extra ao DOM. Eles são ideais para a lógica condicional que tem vários componentes ou elementos adjacentes.</p><pre><code class="language-js">/*
  Podemos aprimorar a lógica do exemplo anterior.
  Se isAuthenticated for verdadeiro, como exibimos os componentes AuthenticatedApp e Footer?
*/
function Header() {
  const isAuthenticated = checkAuth();

  return (
    &lt;nav&gt;
      &lt;Logo /&gt;
      {/* 
        Podemos renderizar os dois componentes com um fragment. 
        Fragments são muito concisos: &lt;&gt; &lt;/&gt;
      */}
      {isAuthenticated ? (
        &lt;&gt;
          &lt;AuthenticatedApp /&gt;
          &lt;Footer /&gt;
        &lt;/&gt;
      ) : (
        &lt;Login /&gt;
      )}
    &lt;/nav&gt;
  );
}
/* 
  Observação: uma sintaxe alternativa para fragments é React.Fragment:
  &lt;React.Fragment&gt;
     &lt;AuthenticatedApp /&gt;
     &lt;Footer /&gt;
  &lt;/React.Fragment&gt;
*/</code></pre><h3 id="listas-e-chaves"><strong>Listas e chaves</strong></h3><p>Use a função <strong><strong>.map()</strong></strong> para converter listas de dados (<em>arrays</em>) em listas de elementos.</p><pre><code class="language-js">const people = ["John", "Bob", "Fred"];
const peopleList = people.map(person =&gt; &lt;p&gt;{person}&lt;/p&gt;);
</code></pre><p><code>.map()</code> pode ser usado para componentes, bem como para elementos JSX simples.</p><pre><code class="language-js">function App() {
  const people = ['John', 'Bob', 'Fred'];
  // pode interpolar a lista retornada de elementos em {}
  return (
    &lt;ul&gt;
      {/* estamos passando cada elemento do array como props para Person */}
      {people.map(person =&gt; &lt;Person name={person} /&gt;}
    &lt;/ul&gt;
  );
}

function Person({ name }) {
  // acessamos a propriedade 'name' diretamente usando a desestruturação de objetos
  return &lt;p&gt;This person's name is: {name}&lt;/p&gt;;
}</code></pre><p>Cada elemento do React em uma lista de elementos precisa de uma <strong><strong><em>key prop</em></strong></strong> especial. As <em>keys </em>são essenciais para que o React possa manter o controle de cada elemento que está sendo iterado com a função <code>.map()</code>.</p><p>O React usa <em>keys</em> (em português, chaves) para atualizar com desempenho elementos individuais quando seus dados são alterados (em vez de renderizar novamente a lista inteira).</p><p>As <em>keys </em>precisam ter valores únicos para que seja possível identificar cada uma delas de acordo com o valor da <em>key</em>.</p><pre><code class="language-js">function App() {
  const people = [
    { id: 'Ksy7py', name: 'John' },
    { id: '6eAdl9', name: 'Bob' },
    { id: '6eAdl9', name: 'Fred' },
  ];

  return (
    &lt;ul&gt;
      {/* as chaves precisam ser valores primitivos, de preferência uma string exclusiva, como um ID */}
      {people.map(person =&gt;
         &lt;Person key={person.id} name={person.name} /&gt;
      )}
    &lt;/ul&gt;
  );
}

// Se você não tiver alguns IDs em seu conjunto de dados que sejam valores únicos e primitivos, use o segundo parâmetro de .map() para obter o índice de cada elemento.

function App() {
  const people = ['John', 'Bob', 'Fred'];

  return (
    &lt;ul&gt;
      {/* usar o índice do elemento do array como chave */}
      {people.map((person, i) =&gt; &lt;Person key={i} name={person} /&gt;)}
    &lt;/ul&gt;
  );
}</code></pre><h3 id="ouvintes-de-eventos-e-tratamento-de-eventos">Ouvintes de eventos e tratamento de evento<strong>s</strong></h3><p>A escuta de eventos em elementos JSX em contraste com elementos HTML difere em alguns aspectos importantes.</p><p>Primeiro, você não pode ouvir eventos em componentes do React – somente em elementos JSX. Adicionar uma propriedade chamada <code>onClick</code>, por exemplo, a um componente do React seria apenas outra propriedade adicionada ao objeto <em>props</em>.</p><pre><code class="language-js">/* 
  A convenção para a maioria das funções de manipulador de eventos é prefixá-las com a palavra 'handle' e, em seguida, com a ação que elas executam (por exemplo, handleToggleTheme)
*/
function handleToggleTheme() {
  // código para alternar o tema da aplicação
}

/* Em HTML, onclick está todo em letras minúsculas, e o manipulador de eventos inclui um conjunto de parênteses após ser referenciado */
&lt;button onclick="handleToggleTheme()"&gt;
  Alterar o tema
&lt;/button&gt;

/* 
  Em JSX, onClick é camelcase, como os atributos / props.
  Também passamos uma referência à função com chaves.
*/
&lt;button onClick={handleToggleTheme}&gt;
  Alterar o tema
&lt;/button&gt;</code></pre><p>Os eventos do React mais importantes a serem conhecidos são <code>onClick</code>, <code>onChange</code> e <code>onSubmit</code>.</p><ul><li><code>onClick</code> lida com eventos de clique em elementos JSX (ou seja, em botões)</li><li><code>onChange</code> trata de eventos de teclado (ou seja, um usuário digitando em um campo de input ou textarea)</li><li><code>onSubmit</code> trata os envios de formulários do usuário</li></ul><pre><code class="language-js">function App() {
  function handleInputChange(event) {
    /* Ao passar a função para um manipulador de eventos, como onChange, obtemos acesso aos dados sobre o evento (um objeto) */
    const inputText = event.target.value; // texto digitado no input
    const inputName = event.target.name; // 'email' do atributo name
  }

  function handleClick(event) {
    /* O onClick normalmente não precisa de dados de eventos, mas também recebe dados de eventos que podemos usar */
    console.log('clicked!');
    const eventType = event.type; // "click"
    const eventTarget = event.target; // &lt;button&gt;Enviar&lt;/button&gt;
  }
    
  function handleSubmit(event) {
    /* 
     Quando pressionarmos o botão de retorno, o formulário será enviado, assim como quando um botão com type=“submit” for clicado.
     Chamamos event.preventDefault() para evitar que o comportamento padrão do formulário ocorra, que é enviar uma solicitação HTTP e recarregar a página.
    */
    event.preventDefault();
    const formElements = event.target.elements; // acessar todos os elementos do formulário
    const inputValue = event.target.elements.emailAddress.value; // acessar o valor do elemento de entrada com o id “emailAddress”
  }

  return (
    &lt;form onSubmit={handleSubmit}&gt;
      &lt;input id="emailAddress" type="email" name="email" onChange={handleInputChange} /&gt;
      &lt;button onClick={handleClick}&gt;Enviar&lt;/button&gt;
    &lt;/form&gt;
  );
}
</code></pre><h2 id="hooks-essenciais-do-react-1">Hooks essenciais do React</h2><h3 id="state-e-usestate"><strong><em>State</em> e useState</strong></h3><p>O hook <code>useState</code> nos fornece o <em>state</em> (em português, estado) em um componente de função. <strong><strong>O </strong><em>state</em></strong> nos permite acessar e atualizar determinados valores em nossos componentes ao longo do tempo.</p><p>O <em>state</em> do componente local é gerenciado pelo hook <code>useState</code> do React, que nos fornece uma variável de <em>state</em> e uma função que nos permite atualizá-la.</p><p>Quando chamamos <code>useState</code>, podemos dar ao nosso <em>state</em> um valor padrão, fornecendo-o como o primeiro argumento quando chamamos <code>useState</code>.</p><pre><code class="language-js">import React from 'react';

/* 
  Como você cria uma variável do state?
  Syntax: const [stateVariable] = React.useState(defaultValue);
*/
function App() {
  const [language] = React.useState('JavaScript');
  /* 
    Usamos a desestruturação do array para declarar a variável do state.
    Como qualquer variável, declaramos que podemos dar a ela o nome que quisermos (neste caso, 'language').
  */

  return &lt;div&gt;Estou aprendendo {language}&lt;/div&gt;;
}</code></pre><p>Observação: qualquer <em>hook</em> nesta seção é da biblioteca principal do React e pode ser importado individualmente.</p><pre><code class="language-js">import React, { useState } from "react";

function App() {
  const [language] = useState("javascript");

  return &lt;div&gt;Estou aprendendo {language}&lt;/div&gt;;
}</code></pre><p><code>useState</code> também nos fornece uma função 'setter' para atualizar o <em>state</em> depois que ele é criado.</p><pre><code class="language-js">function App() {
  /* 
   A função setter é sempre o segundo valor desestruturado.
   A convenção de nomenclatura da função setter deve ser prefixada com 'set'.
  */
  const [language, setLanguage] = React.useState("javascript");

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; setLanguage("python")}&gt;
        Aprenda Python
      &lt;/button&gt;
      {/*  
        Por que usar uma arrow function em linha aqui em vez de chamá-la imediatamente assim: onClick={setterFn()}? 
        Se fosse assim, setLanguage seria chamado imediatamente e não quando o usuário clicasse no botão.
        */}
      &lt;p&gt;Agora estou aprendendo {language}&lt;/p&gt;
    &lt;/div&gt;
  );
}

/* 
 Observação: sempre que a função setter é chamada, o state é atualizado,
 e o componente da aplicação é renderizado novamente para exibir o novo state.
 Sempre que o state for atualizado, o componente será renderizado novamente.
*/</code></pre><p><code>useState</code> pode ser usado uma ou várias vezes em um único componente. Ele pode aceitar valores primitivos ou objetos para gerenciar o <em>state</em>.</p><pre><code class="language-js">function App() {
  const [language, setLanguage] = React.useState("python");
  const [yearsExperience, setYearsExperience] = React.useState(0);

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; setLanguage("javascript")}&gt;
        Alterar a linguagem para JS
      &lt;/button&gt;
      &lt;input
        type="number"
        value={yearsExperience}
        onChange={event =&gt; setYearsExperience(event.target.value)}
      /&gt;
      &lt;p&gt;Agora estou aprendendo {language}&lt;/p&gt;
      &lt;p&gt;Eu tenho {yearsExperience} anos de experiência&lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Se o novo <em>state</em> depender do anterior, para garantir que a atualização seja feita de maneira confiável, podemos usar uma função dentro da função <em>setter</em> que nos forneça o <em>state</em> anterior correto.</p><pre><code class="language-js">/* Temos a opção de organizar o state usando o tipo de dado mais adequado, de acordo com os dados que estamos gerenciando */
function App() {
  const [developer, setDeveloper] = React.useState({
    language: "",
    yearsExperience: 0
  });

  function handleChangeYearsExperience(event) {
    const years = event.target.value;
    /* Devemos passar o objeto de state anterior que tínhamos com o operador spread para distribuir todas as suas propriedades */
    setDeveloper({ ...developer, yearsExperience: years });
  }

  return (
    &lt;div&gt;
      {/* Não há necessidade de obter o state anterior aqui; estamos substituindo o objeto inteiro */}
      &lt;button
        onClick={() =&gt;
          setDeveloper({
            language: "javascript",
            yearsExperience: 0
          })
        }
      &gt;
        Alterar a linguagem para JS
      &lt;/button&gt;
      {/* Também podemos passar uma referência para a função */}
      &lt;input
        type="number"
        value={developer.yearsExperience}
        onChange={handleChangeYearsExperience}
      /&gt;
      &lt;p&gt;Agora estou aprendendo {developer.language}&lt;/p&gt;
      &lt;p&gt;Eu tenho {developer.yearsExperience} anos de experiência&lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Se você estiver gerenciando vários valores primitivos, usar <code>o useState</code> várias vezes geralmente é melhor do que usá-lo uma vez com um objeto. Você não precisa se preocupar em esquecer de combinar o <em>state</em> antigo com o novo.</p><pre><code class="language-js">function App() {
  const [developer, setDeveloper] = React.useState({
    language: "",
    yearsExperience: 0,
    isEmployed: false
  });

  function handleToggleEmployment(event) {
    /* Obtemos o valor da variável do state anterior nos parâmetros.
       Podemos nomear 'prevState' como quisermos.
    */
    setDeveloper(prevState =&gt; {
      return { ...prevState, isEmployed: !prevState.isEmployed };
      // É essencial retornar o novo estado a partir dessa função
    });
  }

  return (
    &lt;button onClick={handleToggleEmployment}&gt;Alternar status de emprego&lt;/button&gt;
  );
}
</code></pre><h3 id="efeitos-colaterais-e-useeffect">Efeitos colaterais e <strong>useEffect</strong></h3><p><code>useEffect</code> nos permite executar efeitos colaterais em componentes de função. Então, o que são efeitos colaterais?</p><p><strong>E<strong>feitos colaterais</strong></strong> ocorrem quando precisamos entrar em contato com o mundo externo. Por exemplo, buscar dados de uma API ou trabalhar com o DOM.</p><p>São ações que podem alterar o <em>state</em> do nosso componente de modo imprevisível (causando 'efeitos colaterais').</p><p><code>useEffect</code> aceita uma função de <em>callback</em> (chamada de função de 'efeito') que, por padrão, será executada sempre que houver uma nova renderização.</p><p>Ela é executada quando nosso componente é montado, que é o momento certo para executar um efeito colateral no ciclo de vida do componente.</p><pre><code class="language-js">/* O que o nosso código faz? Escolhe uma cor do array de cores e a transforma em cor de fundo */
import React, { useState, useEffect } from 'react';

function App() {
  const [colorIndex, setColorIndex] = useState(0);
  const colors = ["blue", "green", "red", "orange"];

  /* 
    Estamos causando um 'efeito colateral', pois estamos trabalhando com uma API.
    Estamos trabalhando com o DOM, uma API do navegador fora do React.
  */
  useEffect(() =&gt; {
    document.body.style.backgroundColor = colors[colorIndex];
  });
  /* Sempre que o state é atualizado, a aplicação é renderizada novamente e o useEffect é executado */

  function handleChangeColor() {
    /* Esse código pode parecer complexo, mas tudo o que ele faz é ir para a próxima cor no array 'colors' e, se estiver na última cor, voltar ao início */
    const nextIndex = colorIndex + 1 === colors.length ? 0 : colorIndex + 1;
    setColorIndex(nextIndex);
  }

  return (
    &lt;button onClick={handleChangeColor}&gt;
      Alterar a cor do fundo
    &lt;/button&gt;
  );
}</code></pre><p>Para evitar a execução da chamada da <em>callback</em> do efeito após cada renderização, fornecemos um segundo argumento, um <em>array</em> vazio.</p><pre><code class="language-js">function App() {
  ...
  /* 
    Com um array vazio, nosso botão não funciona, não importa quantas vezes clicarmos nele... 
    A cor de fundo é definida apenas uma vez, quando o componente é montado pela primeira vez.
  */
  useEffect(() =&gt; {
    document.body.style.backgroundColor = colors[colorIndex];
  }, []);

  /* 
    Como evitar que a função de efeito seja executada a cada atualização de estado e, ainda assim, fazer com que ela funcione sempre que o botão for clicado?
  */

  return (
    &lt;button onClick={handleChangeIndex}&gt;
      Alterar a cor do fundo
    &lt;/button&gt;
  );
}</code></pre><p><code>useEffect</code> nos permite executar efeitos condicionalmente com o <em>array </em>de dependências.</p><p>Um <strong><em>array</em> <strong>de dependências</strong></strong> é o segundo argumento e, se qualquer um dos valores do <em>array </em>for alterado, a função de efeito será executada novamente.</p><pre><code class="language-js">function App() {
  const [colorIndex, setColorIndex] = React.useState(0);
  const colors = ["blue", "green", "red", "orange"];

  /* 
    Vamos adicionar colorIndex ao nosso array de dependências
    Quando o colorIndex for alterado, o useEffect executará a função de efeito novamente
  */
  useEffect(() =&gt; {
    document.body.style.backgroundColor = colors[colorIndex];
    /* 
      Quando usamos o useEffect, precisamos pensar em quais valores de state
      queremos que nosso efeito colateral seja sincronizado
    */
  }, [colorIndex]);

  function handleChangeIndex() {
    const next = colorIndex + 1 === colors.length ? 0 : colorIndex + 1;
    setColorIndex(next);
  }

  return (
    &lt;button onClick={handleChangeIndex}&gt;
      Alterar a cor do fundo
    &lt;/button&gt;
  );
}</code></pre><p><code>useEffect</code> nos permite cancelar a assinatura de determinados efeitos retornando uma função no final.</p><pre><code class="language-js">function MouseTracker() {
  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });

  React.useEffect(() =&gt; {
    // .addEventListener() configura um ouvinte ativo...
    window.addEventListener("mousemove", handleMouseMove);

    /* ...Portanto, quando saímos desta página, ele precisa ser
       removido para parar de ouvir. Caso contrário, ele tentará definir o
       state em um componente que não existe (causando um erro)

     Cancelamos a inscrição de todas as inscrições/ouvintes com essa “função de limpeza”)
     */
    return () =&gt; {
      window.removeEventListener("mousemove", handleMouseMove);
    };
  }, []);

function handleMouseMove(event) {
   setMousePosition({
     x: event.pageX,
     y: event.pageY
   });
}

  return (
    &lt;div&gt;
      &lt;h1&gt;A posição atual do mouse é:&lt;/h1&gt;
      &lt;p&gt;
        X: {mousePosition.x}, Y: {mousePosition.y}
      &lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre><p><code>useEffect</code> é o <em>hook </em>a ser usado quando você quiser fazer uma solicitação HTTP (ou seja, uma solicitação GET quando o componente for montado).</p><p>Observe que o tratamento de <em>promises</em> com a sintaxe mais concisa async/await exige a criação de uma função separada. (Por quê? Porque a função de <em>callback</em> do efeito não pode ser assíncrona).</p><pre><code class="language-js">const endpoint = "https://api.github.com/users/reedbarger";

// Usando funções de callback .then() para resolver a promise
function App() {
  const [user, setUser] = React.useState(null);

  React.useEffect(() =&gt; {
    fetch(endpoint)
      .then(response =&gt; response.json())
      .then(data =&gt; setUser(data));
  }, []);
}

// Usando a sintaxe async/ await para resolver a promise:
function App() {
  const [user, setUser] = React.useState(null);
  // não é possível tornar assíncrona a função de callback useEffect
  React.useEffect(() =&gt; {
    getUser();
  }, []);

  // Devemos aplicar a palavra-chave async a uma função separada
  async function getUser() {
    const response = await fetch(endpoint);
    const data = await response.json();
    setUser(data);
  }
}
</code></pre><h3 id="refs-e-useref"><strong>Refs e useRef</strong></h3><p><strong><strong>Refs</strong></strong> são um atributo especial que está disponível em todos os componentes do React. Eles nos permitem criar uma referência a um determinado elemento/componente quando o componente é montado.</p><p>O <code>useRef</code> nos permite usar facilmente as <code>refs</code> do React. Chamamos useRef (na parte superior do componente) e anexamos o valor retornado ao atributo <code>ref</code> do elemento para fazer referência a ele.</p><p>Depois de criarmos uma referência, usamos a propriedade <code>current</code> para modificar (silenciar) as propriedades do elemento ou podemos chamar quaisquer métodos disponíveis nesse elemento (como <code>.focus()</code> para focalizar uma entrada).</p><pre><code class="language-js">function App() {
  const [query, setQuery] = React.useState("react hooks");
  /* Podemos passar um valor padrão para useRef.
     Não precisamos dele aqui, então passamos null para fazer referência a um objeto vazio
  */
  const searchInput = useRef(null);

  function handleClearSearch() {
    /* 
      .current faz referência ao elemento de entrada na montagem
      useRef pode armazenar basicamente qualquer valor em sua propriedade .current
    */
    searchInput.current.value = "";
    searchInput.current.focus();
  }

  return (
    &lt;form&gt;
      &lt;input
        type="text"
        onChange={event =&gt; setQuery(event.target.value)}
        ref={searchInput}
      /&gt;
      &lt;button type="submit"&gt;Buscar&lt;/button&gt;
      &lt;button type="button" onClick={handleClearSearch}&gt;
        Limpar
      &lt;/button&gt;
    &lt;/form&gt;
  );
}
</code></pre><h2 id="hooks-e-desempenho-1"><strong>Hooks e desempenho</strong></h2><h3 id="preven-o-de-novas-renderiza-es-e-react-memo"><strong>Prevenção de novas renderizações e React.memo</strong></h3><p><code>React.memo</code> é uma função que nos permite otimizar o modo como nossos componentes são renderizados.</p><p>Em particular, ela executa um processo chamado <strong><strong>memoização </strong></strong>que nos ajuda a evitar que nossos componentes sejam renderizados novamente quando não for necessário (consulte React.useMemo para obter uma definição mais completa de memoização).</p><p><code>O React.memo</code> ajuda mais a evitar que listas de componentes sejam renderizadas novamente quando seus componentes pai são renderizados novamente.</p><pre><code class="language-js">/* 
  Na aplicação a seguir, estamos mantendo o controle de nossas habilidades de programação. Podemos criar novas habilidades usando uma entrada, e elas são adicionadas à lista (mostrada no componente SkillList). Se clicarmos em uma habilidade, ela será excluída.
*/

function App() {
  const [skill, setSkill] = React.useState('')
  const [skills, setSkills] = React.useState([
    'HTML', 'CSS', 'JavaScript'
  ])

  function handleChangeInput(event) {
    setSkill(event.target.value);
  }

  function handleAddSkill() {
    setSkills(skills.concat(skill))
  }

  return (
    &lt;&gt;
      &lt;input onChange={handleChangeInput} /&gt;
      &lt;button onClick={handleAddSkill}&gt;Adicionar habilidade&lt;/button&gt;
      &lt;SkillList skills={skills} /&gt;
    &lt;/&gt;
  );
}

/* O problema, se você mesmo executar esse código, é que, quando digitamos no input, como o componente pai da SkillList (App) é renderizado novamente, devido à atualização do state a cada pressionamento de tecla, a SkillList é renderizada constantemente (conforme indicado pelo console.log) */

/* No entanto, quando envolvemos o componente SkillList no React.memo (que é uma função de ordem superior, o que significa que ele aceita uma função como argumento), ele não será mais renderizado desnecessariamente quando nosso componente pai o fizer. */
const SkillList = React.memo(({ skills }) =&gt; {
  console.log('renderizando novamente');
  return (
    &lt;ul&gt;
    {skills.map((skill, i) =&gt; &lt;li key={i}&gt;{skill}&lt;/li&gt;)}
    &lt;/ul&gt;
  )
})

export default App</code></pre><h3 id="fun-es-de-callback-e-usecallback"><strong>Funções de <em>callback</em> e useCallback</strong></h3><p><code>useCallback</code> é um <em>hook </em>usado para melhorar o desempenho do nosso componente. <strong>F<strong>un</strong>ções de</strong> <strong><em>c<strong>allback</strong></em><strong> </strong></strong>são os nomes das funções que são "chamadas de volta" em um componente pai.</p><p>O uso mais comum é ter um componente pai com uma variável de <em>state</em>, mas você deseja atualizar esse estado em um componente filho. O que você faz? Você passa uma função de <em>callback</em> para o filho a partir do pai. Isso nos permite atualizar o <em>state</em> no componente pai.</p><p><code>useCallback</code> funciona de maneira semelhante ao <code>React.memo</code>. Ele memoriza as funções de <em>callback</em>, para que não sejam recriadas a cada nova renderização. O uso correto do <code>useCallback</code> pode melhorar o desempenho da nossa aplicação.</p><pre><code class="language-js">/* Vamos manter exatamente a mesma aplicação acima com o React.memo, mas adicionar uma pequena funcionalidade. Vamos permitir a exclusão de uma habilidade quando clicarmos nela. Para fazer isso, precisamos filtrar o array de habilidades de acordo com a habilidade em que clicamos. Para isso, criamos a função handleRemoveSkill no App */

function App() {
  const [skill, setSkill] = React.useState('')
  const [skills, setSkills] = React.useState([
    'HTML', 'CSS', 'JavaScript'
  ])

  function handleChangeInput(event) {
    setSkill(event.target.value);
  }

  function handleAddSkill() {
    setSkills(skills.concat(skill))
  }

  function handleRemoveSkill(skill) {
    setSkills(skills.filter(s =&gt; s !== skill))
  }
    
  /* Em seguida, passamos handleRemoveSkill como uma prop ou, como se trata de uma função, como uma função de callback a ser usada na SkillList */
  return (
    &lt;&gt;
      &lt;input onChange={handleChangeInput} /&gt;
      &lt;button onClick={handleAddSkill}&gt;Adicionar habilidade&lt;/button&gt;
      &lt;SkillList skills={skills} handleRemoveSkill={handleRemoveSkill} /&gt;
    &lt;/&gt;
  );
}

/* Quando tentamos digitar a entrada novamente, vemos uma nova renderização no console toda vez que digitamos. Nossa memoização do React.memo está quebrada! 

O que está acontecendo é que a função de callback handleRemoveSkill está sendo recriada toda vez que a aplicação é renderizada, fazendo com que todos os filhos também sejam renderizados. Precisamos envolver handleRemoveSkill em useCallback e fazer com que ela seja recriada somente quando o valor da habilidade for alterado.

Para corrigir nossa aplicação, substitua handleRemoveSkill por:

const handleRemoveSkill = React.useCallback((skill) =&gt; {
  setSkills(skills.filter(s =&gt; s !== skill))
}, [skills])

Experimente você mesmo!
*/
const SkillList = React.memo(({ skills, handleRemoveSkill }) =&gt; {
  console.log('renderizando novamente');
  return (
    &lt;ul&gt;
    {skills.map(skill =&gt; &lt;li key={skill} onClick={() =&gt; handleRemoveSkill(skill)}&gt;{skill}&lt;/li&gt;)}
    &lt;/ul&gt;
  )
})


export default App</code></pre><h3 id="memoiza-o-e-usememo">Memoização e useMemo</h3><p><code>useMemo</code> é muito semelhante ao <code>useCallback</code> e serve para melhorar o desempenho. Em vez de ser para <em>callbacks</em>, no entanto, ele serve para armazenar os resultados de cálculos custosos.</p><p><code>useMemo</code> nos permite <strong><strong>memoizar</strong></strong> ou lembrar o resultado de cálculos custosos quando eles já foram feitos para determinadas entradas.</p><p>Memoização significa que, se um cálculo já foi feito antes com uma determinada entrada, não há necessidade de fazê-lo novamente, pois já temos o resultado armazenado dessa operação.</p><p><code>useMemo</code> retorna um valor do cálculo, que é então armazenado em uma variável.</p><pre><code class="language-js">/* Com base em nossa aplicação de habilidades, vamos adicionar um recurso para pesquisar nossas habilidades disponíveis por meio de uma entrada de pesquisa adicional. Podemos adicionar isso em um componente chamado SearchSkills (mostrado acima da nossa SkillList).
*/

function App() {
  const [skill, setSkill] = React.useState('')
  const [skills, setSkills] = React.useState([
    'HTML', 'CSS', 'JavaScript', ...milhares de outros itens
  ])

  function handleChangeInput(event) {
    setSkill(event.target.value);
  }

  function handleAddSkill() {
    setSkills(skills.concat(skill))
  }

  const handleRemoveSkill = React.useCallback((skill) =&gt; {
    setSkills(skills.filter(s =&gt; s !== skill))
  }, [skills])
   
  return (
    &lt;&gt;
      &lt;SearchSkills skills={skills} /&gt;
      &lt;input onChange={handleChangeInput} /&gt;
      &lt;button onClick={handleAddSkill}&gt;Adicionar habilidade&lt;/button&gt;
      &lt;SkillList skills={skills} handleRemoveSkill={handleRemoveSkill} /&gt;
    &lt;/&gt;
  );
}

/* Vamos imaginar que temos uma lista de milhares de habilidades que queremos pesquisar. Como podemos encontrar e mostrar de modo eficiente as habilidades que correspondem ao nosso termo de pesquisa à medida que o usuário digita? */
function SearchSkills() {
  const [searchTerm, setSearchTerm] = React.useState('');  
      
  /* Usamos o React.useMemo para memorizar (lembrar) o valor retornado de nossa operação de pesquisa e executá-lo somente quando o searchTerm for alterado */
  const searchResults = React.useMemo(() =&gt; {
    return skills.filter((s) =&gt; s.includes(searchTerm);
  }), [searchTerm]);
    
  function handleSearchInput(event) {
    setSearchTerm(event.target.value);
  }
    
  return (
    &lt;&gt;
    &lt;input onChange={handleSearchInput} /&gt;
    &lt;ul&gt;
      {searchResults.map((result, i) =&gt; &lt;li key={i}&gt;{result}&lt;/li&gt;
    &lt;/ul&gt;
    &lt;/&gt;
  );
}


export default App</code></pre><h2 id="hooks-avan-ados-no-react"><strong>Hooks </strong>avançados no<strong> React </strong></h2><h3 id="contexto-e-usecontext"><strong>Contexto e useContext</strong></h3><p>No React, queremos evitar o seguinte problema de criar várias <em>props</em> para passar dados para dois ou mais níveis abaixo de um componente principal.</p><pre><code class="language-js">/* 
  O React Context nos ajuda a evitar a criação de várias props duplicadas.
  Esse padrão também é chamado de perfuração de props.
*/

/* Nesta aplicação, queremos passar os dados do usuário para o componente Header, mas primeiro eles precisam passar por um componente Main que não os utiliza */
function App() {
  const [user] = React.useState({ name: "Fred" });

  return (
    // Primeira prop 'user'
    &lt;Main user={user} /&gt;
  );
}

const Main = ({ user }) =&gt; (
  &lt;&gt;
    {/* Segunda prop 'user' */}
    &lt;Header user={user} /&gt;
    &lt;div&gt;Conteúdo do Main...&lt;/div&gt;
  &lt;/&gt;
);

const Header = ({ user }) =&gt; &lt;header&gt;Bem vindo, {user.name}!&lt;/header&gt;;</code></pre><p>O contexto é útil para transmitir <em>props </em>em vários níveis de componentes filhos a partir de um componente pai.</p><pre><code class="language-js">/* 
  Aqui está o exemplo anterior reescrito com o Context.
  Primeiro, criamos o contexto, no qual podemos passar os valores padrão.
  Chamamos isso de "UserContext" porque estamos transmitindo dados do usuário
*/
const UserContext = React.createContext();

function App() {
  const [user] = React.useState({ name: "Fred" });

  return (
    {/* 
      Envolvemos o componente pai com a propriedade Provider.
      Passamos os dados pela árvore de componentes na propriedade value.
     */}
    &lt;UserContext.Provider value={user}&gt;
      &lt;Main /&gt;
    &lt;/UserContext.Provider&gt;
  );
}

const Main = () =&gt; (
  &lt;&gt;
    &lt;Header /&gt;
    &lt;div&gt;Conteúdo do app Main&lt;/div&gt;
  &lt;/&gt;
);

/* 
  Não podemos remover as duas propriedades 'user'. Em vez disso, podemos simplesmente usar a propriedade Consumer para consumir os dados onde precisamos deles
*/
const Header = () =&gt; (
    {/* Usamos um padrão chamado render props para obter acesso aos dados */}
    &lt;UserContext.Consumer&gt;
      {user =&gt; &lt;header&gt;Bem vindo, {user.name}!&lt;/header&gt;}
    &lt;/UserContext.Consumer&gt;
);</code></pre><p>O hook <code>useContext</code> nos permite consumir o contexto em qualquer componente de função que seja filho do provedor, em vez de usar o padrão de renderização das <em>props</em>.</p><pre><code class="language-js">function Header() {
  /* Passamos o objeto de contexto inteiro para consumi-lo e podemos remover as tags de Consumer */
  const user = React.useContext(UserContext);
    
  return &lt;header&gt;Bem vindo, {user.name}!&lt;/header&gt;;
};
</code></pre><h3 id="redutores-e-usereducer"><strong>Redutores e useReducer</strong></h3><p>Os redutores são funções simples e previsíveis (puras) que recebem um objeto de <em>state</em> anterior e um objeto de ação e retornam um novo objeto de <em>state</em>.</p><pre><code class="language-js">/* Esse redutor gerencia o state do usuário em nossa aplicação: */

function userReducer(state, action) {
  /* Os redutores geralmente usam um comando switch para atualizar o state de uma maneira ou de outra com base na propriedade de tipo da ação */
    
  switch (action.type) {
    /* Se action.type tiver a string 'LOGIN', obteremos dados do objeto payload na ação */
    case "LOGIN":
      return { 
        username: action.payload.username, 
        email: action.payload.email
        isAuth: true 
      };
    case "SIGNOUT":
      return { 
        username: "",
        email: "",
        isAuth: false 
      };
    default:
      /* Se nenhum caso corresponder à ação recebida, retorne ao state anterior */
      return state;
  }
}</code></pre><p>Redutores são um padrão poderoso para gerenciar <em>states</em>, usado na popular biblioteca de gerenciamento de state do Redux (comumente usada com o React).</p><p>Os redutores podem ser usados no React com o <em>hook</em> <code>useReducer</code> para gerenciar o <em>state</em> em toda a aplicação, em comparação com o useState (que é para o <em>state</em> do componente local).</p><p>O <code>useReducer</code> pode ser combinado com o <code>useContext</code> para gerenciar dados e transmiti-los facilmente entre os componentes.</p><p>Assim, <code>useReducer</code> + <code>useContext</code> pode ser um sistema completo de gerenciamento de <em>state</em> para nossas aplicações.</p><pre><code class="language-js">const initialState = { username: "", isAuth: false };

function reducer(state, action) {
  switch (action.type) {
    case "LOGIN":
      return { username: action.payload.username, isAuth: true };
    case "SIGNOUT":
      // também poderia se espalhar no initialState aqui
      return { username: "", isAuth: false };
    default:
      return state;
  }
}

function App() {
  // useReducer requer uma função redutora para ser usada e um initialState
  const [state, dispatch] = useReducer(reducer, initialState);
  // Obtemos o resultado atual do redutor em 'state'

  // usamos o dispatch para 'despachar' ações, para executar nosso redutor
  // com os dados de que ele precisa (o objeto de ação)
  function handleLogin() {
    dispatch({ type: "LOGIN", payload: { username: "Ted" } });
  }

  function handleSignout() {
    dispatch({ type: "SIGNOUT" });
  }

  return (
    &lt;&gt;
      Usuário atual: {state.username}, isAuthenticated: {state.isAuth}
      &lt;button onClick={handleLogin}&gt;Login&lt;/button&gt;
      &lt;button onClick={handleSignout}&gt;Signout&lt;/button&gt;
    &lt;/&gt;
  );
}</code></pre><h3 id="escrevendo-hooks-personalizados">Escrevendo <em>hooks </em>personalizados</h3><p>Os <em>hooks </em>foram criados para reutilizar facilmente um comportamento entre componentes, da mesma forma que os componentes foram criados para reutilizar a estrutura em nossa aplicação.</p><p>Os <em>hooks </em>nos permitem adicionar funcionalidades personalizadas às nossas aplicações que atendam às nossas necessidades e podem ser combinados com todos os <em>hooks </em>existentes que abordamos.</p><p>Os <em>hooks </em>também podem ser incluídos em bibliotecas de terceiros para o bem de todos os desenvolvedores do React. Há muitas bibliotecas React excelentes que fornecem <em>hooks </em>personalizados, como <code>@apollo/client</code>, <code>react-query</code>, <code>swr</code> e outras.</p><pre><code class="language-js">/* Aqui está um hook personalizado do React chamado useWindowSize que escrevi para calcular o tamanho da janela (largura e altura) de qualquer componente no qual ele é usado */

import React from "react";

export default function useWindowSize() {
  const isSSR = typeof window !== "undefined";
  const [windowSize, setWindowSize] = React.useState({
    width: isSSR ? 1200 : window.innerWidth,
    height: isSSR ? 800 : window.innerHeight,
  });

  function changeWindowSize() {
    setWindowSize({ width: window.innerWidth, height: window.innerHeight });
  }

  React.useEffect(() =&gt; {
    window.addEventListener("resize", changeWindowSize);

    return () =&gt; {
      window.removeEventListener("resize", changeWindowSize);
    };
  }, []);

  return windowSize;
}

/* Para usar o hook, basta importá-lo para onde for necessário, chamá-lo e usar a largura sempre que quisermos ocultar ou mostrar determinados elementos, como em um componente Header. */

// components/Header.js

import React from "react";
import useWindowSize from "../utils/useWindowSize";

function Header() {
  const { width } = useWindowSize();

  return (
    &lt;div&gt;
      {/* visível somente quando a janela for maior que 500px */}
      {width &gt; 500 &amp;&amp; (
        &lt;&gt;
         Maior que 500px!
        &lt;/&gt;
      )}
      {/* visível em qualquer tamanho de janela */}
	  &lt;p&gt;Estou sempre visível&lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre><h3 id="regras-dos-hooks"><strong>Regras dos hooks</strong></h3><p>Há duas regras essenciais para o uso de <em>hooks </em>do React que não podem ser violadas para que funcionem corretamente:</p><ul><li>Os <em>hooks </em>só podem ser usados em componentes de função (não em funções JavaScript simples ou componentes de classe)</li><li>Os <em>hooks </em>só podem ser chamados na parte superior dos componentes (não podem estar em condicionais, laços ou funções aninhadas)</li></ul><h2 id="conclus-o"><strong><strong><strong>Conclusão</strong></strong></strong></h2><p>Há outros conceitos interessantes que você pode aprender, mas se você se comprometer a aprender os conceitos abordados nesta ficha informativa, terá uma ótima compreensão das partes mais importantes e poderosas da biblioteca do React.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como criar seu primeiro gráfico em JavaScript com o JSCharting ]]>
                </title>
                <description>
                    <![CDATA[ Quando se está começando como desenvolvedor JavaScript iniciante, acho que é importante buscar projetos interessantes. Assim, você pode se divertir enquanto aprende e provavelmente encontrará uma área de especialização que seja do seu agrado. Como se costuma dizer, "se você ama o que faz, nunca trabalhará um dia sequer em ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-criar-seu-primeiro-grafico-em-javascript-com-o-jscharting/</link>
                <guid isPermaLink="false">65568961f2994303ed34426e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Filipe Virgínio Vital Torres Barbosa ]]>
                </dc:creator>
                <pubDate>Tue, 14 May 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/first-javascript-chart-using-csv-jscharting-fit.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-make-your-first-javascript-chart/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to make your first JavaScript chart with JSCharting</a>
      </p><p>Quando se está começando como desenvolvedor JavaScript iniciante, acho que é importante buscar projetos interessantes. Assim, você pode se divertir enquanto aprende e provavelmente encontrará uma área de especialização que seja do seu agrado.</p><p>Como se costuma dizer, <em>"se você ama o que faz, nunca trabalhará um dia sequer em sua vida"</em>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/not-suited-for-work.gif" class="kg-image" alt="not-suited-for-work" width="480" height="266" loading="lazy"><figcaption>Fonte: giphy.com</figcaption></figure><p>Neste artigo, apresentarei a visualização de dados de front-end, que é minha paixão pessoal. Talvez ela também se torne sua paixão!</p><p>Os momentos mais gratificantes para mim como desenvolvedor são quando posso ver ou experimentar os resultados do que criei. É muito gratificante criar um gráfico que revela insights interessantes sobre seus dados ou uma experiência interativa que ajuda a explorar detalhes de um conjunto de dados exclusivo. Quanto mais significativo for o resultado, mais gratificante será a sensação.</p><p>No entanto, percebi que a quantidade de trabalho que você dedica a um projeto não está necessariamente relacionada à sensação de realização – às vezes, a sensação é ótima mesmo quando foi relativamente fácil.</p><p>Com o tempo, você encontrará ferramentas que o ajudarão a ser mais eficiente e, às vezes, você moverá montanhas com pouco esforço. Há muitas bibliotecas de gráficos e ferramentas disponíveis na área de visualização de dados. Com as ferramentas certas, você criará novos gráficos com pouco esforço, independentemente do tipo de gráfico de que precisar. Pessoalmente, acho que a visualização dos dados gera uma grande recompensa pelo seu investimento de tempo e esforço.</p><p>Neste tutorial, você usará várias ferramentas para obter dados pela Internet, processará esses dados e desenhará um belo gráfico que pode ser visualizado em qualquer navegador moderno. Você pode clicar nos links abaixo para baixar o código de exemplo de cada etapa individualmente, visualizar todos no <strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article">GitHub</a></strong></strong>, ou baixar todas as etapas de uma só vez aqui: <strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/all-steps.zip">all-steps.zip</a>.</strong></strong></p><h2 id="o-resultado"><strong>O resultado</strong></h2><p>Ao final do tutorial, você criará este gráfico interativo orientado por dados. Você aprenderá a obter dados pela Internet, a processá-los e a criar um gráfico com esses dados. Você também poderá criar seus próprios gráficos do zero.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/javascript-line-chart.png" class="kg-image" alt="javascript-line-chart" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/javascript-line-chart.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/javascript-line-chart.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/javascript-line-chart.png 1282w" sizes="(min-width: 720px) 720px" width="1282" height="536" loading="lazy"><figcaption>Gráfico de linha interativo feito em JavaScript</figcaption></figure><p>Depois de processar os dados e fazer o gráfico, você também aprenderá a fazer ajustes no gráfico, incluindo a modificação da legenda padrão, a ativação de pontos de foco (em inglês, <em>crosshairs</em>) no eixo x com dicas (em inglês, <em>tooltips</em>) e a aplicação de anotações de texto para adicionar contexto e outras informações ao gráfico.</p><h2 id="as-ferramentas"><strong>As ferramentas</strong></h2><p>Para começar, use um navegador da internet como o que você provavelmente está usando para ler este artigo. Recomendo o Chrome, pois ele oferece uma ótima experiência e ferramentas integradas para desenvolvedores.</p><p>Em seguida, você precisará de um editor de texto. Algo simples como o bloco de notas funcionará. No entanto, sugiro usar um editor de código mais avançado, como o VS Code, pois esse é um ambiente no qual você passará muito tempo. Ele proporcionará a você uma experiência de programação mais conveniente e agradável, além de tornar a escrita em HTML5, CSS e JavaScript mais agradável aos olhos. O mais importante é que, se você esquecer uma citação ou uma vírgula em algum lugar, um editor de código poderá ajudá-lo a encontrar o erro.</p><p>Este artigo pode ajudá-lo a <a href="https://www.freecodecamp.org/news/how-to-choose-a-javascript-code-editor/">escolher o melhor editor de código em JavaScript para o desenvolvimento para a Web</a> (texto em inglês).</p><p>Você usará a biblioteca de gráficos JSCharting para desenhar e adicionar a funcionalidade interativa ao gráfico automaticamente. Não serão necessárias outras bibliotecas do JavaScript, como o jQuery, ou plataformas de front-end, como o React e o Angular (comumente usadas em projetos de sites).</p><h3 id="por-que-jscharting"><strong>Por que JSCharting?</strong></h3><p>O JSCharting é uma biblioteca de gráficos em JavaScript que pode desenhar muitos tipos diferentes de gráficos usando SVG. Ela é fácil de usar e de começar a aprender, sendo, portanto, é uma boa opção para este tutorial. A API (Interface de Programação de Aplicativos, ou seja, as opções e configurações necessárias para criar gráficos) torna as coisas difíceis mais simples e é uma boa opção para fazer experiências com visualizações de dados.</p><p>Você pode usar o JSCharting gratuitamente para uso pessoal e comercial com a marca incluída.</p><p>Você pode criar gráficos responsivos com o JSCharting por meio de algumas etapas simples:</p><ul><li>Defina uma tag <code>&lt;div&gt;</code> no HTML com um ID único.</li><li>Forneça essa id, os dados e quaisquer outras opções ao chamar <code>JSC.Chart()</code> no arquivo JavaScript.</li></ul><p>É isso. O JSC desenhará um gráfico de aparência profissional preenchendo essa tag div com elementos visuais em SVG. O gráfico será responsivo e interativo sem nenhum esforço extra.</p><h2 id="os-dados"><strong>Os dados</strong></h2><p>Você usará um arquivo de dados fornecido pelo NCHS (National Center for Health Statistics, o Centro Nacional de Estatísticas em Saúde) que lista a expectativa de vida histórica de homens e mulheres nos EUA.</p><p>Você pode encontrar esses dados aqui: <a href="https://data.cdc.gov/resource/w9j2-ggv5.csv">https://data.cdc.gov/resource/w9j2-ggv5.csv</a>.</p><p>Esse arquivo CSV contém dados que categorizam as expectativas de vida por ano, raça e sexo. Você usará alguns desses dados para desenhar uma simples linha de tendência para homens e mulheres nos últimos 100 anos.</p><p>O arquivo CSV (de <em>Comma Separated Values</em>, que significa valores separados por vírgula) é um formato muito bom para transmitir dados pela Internet. É compacto, legível por humanos e você pode abri-lo diretamente no Excel, o que também é ótimo.</p><p>Portanto, sem mais delongas, vamos começar.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/readycat.gif" class="kg-image" alt="readycat" width="480" height="452" loading="lazy"><figcaption>Fonte: giphy.com</figcaption></figure><h2 id="passo-1-adicionar-um-gr-fico-em-branco"><strong>Passo 1 – </strong>adicionar um gráfico em branco</h2><p>O primeiro arquivo zip contém um ponto de partida em branco que pode ser preenchido à medida que avançamos. Se você se perder ou ficar confuso, ou se quiser pular adiante, o arquivo zip no final ou ao longo de cada seção o deixará atualizado.</p><p>Se desejar fazer o download de todos os arquivos de uma só vez, pegue o arquivo <strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/all-steps.zip">all-steps.zip</a></strong></strong><em><em>.</em></em></p><h3 id="step1-a-zip"><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step1-a.zip">step1-a.zip</a></strong></h3><p>Esse arquivo zip contém os seguintes arquivos:</p><ul><li><code>index.html</code></li><li><code>js/index.js</code></li></ul><p>O arquivo <code>.html</code> está vazio, exceto por algum código padrão que o torna um arquivo válido, enquanto o arquivo <code>.js</code> está completamente vazio.</p><p>A primeira coisa a fazer é adicionar alguns scripts ao arquivo HTML da página da Web. Normalmente, as pessoas sugerem adicionar tags <code>&lt;script&gt;</code> dentro das tags <code>&lt;head&gt;</code>. No entanto, para scripts que afetam o conteúdo HTML, geralmente é melhor adicioná-los após o fechamento da tag <code>&lt;/body&gt;</code>.</p><p>Essa técnica carrega todo o HTML no DOM antes de executar qualquer JavaScript. O gráfico precisa do HTML carregado antes de poder desenhar nele. O DOM (de <em>Document Object Model</em> – em português, Modelo de Objeto de Documentos) é uma representação de seu código HTML na memória do navegador. Depois que o HTML é carregado no DOM, o navegador pode exibi-lo e o JavaScript pode interagir com ele.</p><p>Comece adicionando a biblioteca JSCharting ao arquivo HTML. Abra o arquivo <code>index.html</code> no editor de sua preferência. Em seguida, adicione uma tag de script para incluir o JSCharting após a tag de fechamento <code>&lt;/body&gt;</code>. O código resultante na parte inferior do arquivo deve ter a seguinte aparência:</p><pre><code class="language-html">&lt;/body&gt;
&lt;script src="https://code.jscharting.com/2.9.0/jscharting.js"&gt;&lt;/script&gt;
&lt;/html&gt;</code></pre><p>O URL dessa biblioteca aponta para uma CDN (<em>Content Delivery Network</em> – em português, rede de distribuição de conteúdo). Ela hospeda o código do gráfico e torna conveniente adicionar rapidamente a biblioteca a qualquer página HTML para criar protótipos de gráficos e fazer experimentos. Você também pode <a href="https://jscharting.com/download/">baixar</a> e usar a biblioteca localmente ou usar o pacote npm em seu projeto, mas a CDN não exige nenhuma etapa adicional.</p><p>Em seguida, usando a mesma técnica, adicione outra tag de script fazendo referência ao seu arquivo JavaScript em branco. Adicione esse script após o script de <code>jscharting.js</code> para que tenha a seguinte aparência:</p><pre><code class="language-html">&lt;/body&gt;
&lt;script src="https://code.jscharting.com/2.9.0/jscharting.js"&gt;&lt;/script&gt;
&lt;script src="js/index.js"&gt;&lt;/script&gt;
&lt;/html&gt;</code></pre><p>Ótimo. Estamos quase prontos para desenhar um gráfico em branco. A última coisa que você precisa fazer é adicionar uma tag <code>&lt;div&gt;</code> dentro do arquivo HTML para definir onde queremos que este gráfico seja desenhado.</p><p>Adicione este código HTML dentro das tags <code>&lt;body&gt;</code>.</p><pre><code class="language-html">&lt;body&gt;
    &lt;div id="chartDiv" style="width:50%; height:300px; margin:0 auto;"&gt;&lt;/div&gt;
&lt;/body&gt;</code></pre><p>A div deve ter um id para que você possa informar ao gráfico em qual div deve ser desenhada. Nesse caso, o id é <code>chartDiv</code>.</p><p>Você pode notar o atributo style da tag <code>&lt;div&gt;</code>. Ele faz com que a div tenha 50% da largura da janela e 300 pixels de altura. O estilo de margem <code>margin: 0 auto;</code> centraliza a div na página. O gráfico será preenchido independentemente do tamanho da div, portanto, alterar o tamanho da div é uma boa maneira de controlar o tamanho do gráfico.</p><p>Está tudo pronto com o arquivo HTML. Abra o arquivo <code>index.js</code> e adicione um gráfico em branco a essa página escrevendo o seguinte código, que inclui a div id <code>chartDiv</code>:</p><pre><code class="language-javascript">JSC.Chart('chartDiv', {});</code></pre><p>Abra o arquivo <code>index.html</code> em um navegador (arraste e solte o arquivo em um navegador da Web como o Chrome).</p><p>Ainda não há muito para ver, mas você pode notar um pequeno logotipo da JSC nesta página. Isso indica que um gráfico está conectado e sendo desenhado.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/jscharting-brand.png" class="kg-image" alt="jscharting-brand" width="104" height="63" loading="lazy"><figcaption>A logo do JSCharting mostra que o gráfico está funcionando</figcaption></figure><p><strong><strong><strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step1-b.zip">step1-b.zip</a></strong></strong></strong></strong></p><h2 id="passo-2-brinque-um-pouco-com-o-gr-fico"><strong>Passo 2 – b</strong>rinque um pouco com o gráfico</h2><p>Para testar, vamos adicionar alguns valores para o gráfico visualizar e ver como ele funciona.</p><p>Voltando ao arquivo <code>index.js</code>, substitua o conteúdo pelo código a seguir, que adiciona mais opções ao gráfico.</p><pre><code class="language-javascript">JSC.Chart('chartDiv', {
   type: 'horizontal column',
   series: [
      {
         points: [
            {x: 'Apples', y: 50},
            {x: 'Oranges', y: 42}
         ]
      }
   ]
});</code></pre><p>Agora, atualize (F5) a janela do navegador onde a página <code>index.html</code> está carregada.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/horizontal-column-chart.png" class="kg-image" alt="horizontal-column-chart" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/horizontal-column-chart.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/horizontal-column-chart.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/horizontal-column-chart.png 1064w" sizes="(min-width: 720px) 720px" width="1064" height="454" loading="lazy"><figcaption>Gráfico de barras horizontais com uma série e dois pontos</figcaption></figure><p>Muito bom! Você acabou de criar seu primeiro gráfico usando JavaScript.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/yeah-1.gif" class="kg-image" alt="yeah-1" width="335" height="230" loading="lazy"><figcaption>Fonte: giphy.com</figcaption></figure><p>Você criou um gráfico de barras ao definir a opção de tipo de gráfico como <code>'horizontal column'</code>. Se você preferir uma coluna vertical, defina o valor como <code>'column'</code>. Você também adicionou uma série com dois pontos ao gráfico para Maçãs e Laranjas (<em>Apples</em> e <em>Oranges</em>, em inglês, respectivamente).</p><p>Todos os dados do gráfico são compostos de séries e pontos. Uma série é simplesmente um grupo de pontos de dados. Os gráficos podem conter uma ou mais séries de dados. Os pontos de dados consistem em valores que mapeiam os eixos x e y. Os pontos também podem incluir muitas outras variáveis e valores descritivos.</p><p>O exemplo acima contém apenas uma série. Agora vamos dar uma olhada nas opções para um gráfico com duas séries. Substitua o conteúdo do arquivo JavaScript por este código.</p><pre><code class="language-javascript">JSC.Chart('chartDiv', {
   type: 'horizontal column',
   series: [
      {
         name:'Andy',
         points: [
            {x: 'Apples', y: 50},
            {x: 'Oranges', y: 32}
         ]
      },{
         name:'Anna',
         points: [
            {x: 'Apples', y: 30},
            {x: 'Oranges', y: 22}
         ]
      }
   ]
});</code></pre><p>Ao atualizar da janela do navegador será exibido este gráfico.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/horizontal-column-cluster.png" class="kg-image" alt="horizontal-column-cluster" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/horizontal-column-cluster.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/horizontal-column-cluster.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/horizontal-column-cluster.png 1065w" sizes="(min-width: 720px) 720px" width="1065" height="459" loading="lazy"><figcaption>Gráfico de barras horizontais com duas séries</figcaption></figure><p>As opções do gráfico são semelhantes. Ainda é um gráfico de barras, mas dessa vez há um objeto extra no array de séries. &nbsp;Também adicionamos propriedades de nome para cada série para que o gráfico possa identificá-las na legenda.</p><p>Se estiver interessado em criar gráficos diferentes, como gráficos de radar, gráficos de área, gráficos de pizza, gráficos de Gantt ou até mesmo gráficos de mapa de calor de calendário, dê uma olhada na <a href="https://jscharting.com/examples/chart-types/">galeria de exemplos do JSCharting</a> e o código-fonte (opções de gráfico) usado para criar esses gráficos. Você pode aprender rapidamente a usar outros recursos de gráficos copiando os exemplos disponíveis.</p><p><strong><strong><strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step2.zip">step2.zip</a></strong></strong></strong></strong></p><h2 id="passo-3-prepare-os-dados"><strong>Passo 3 – prepare os dados</strong></h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/data.gif" class="kg-image" alt="data" width="448" height="352" loading="lazy"><figcaption>Fonte: giphy.com</figcaption></figure><p>O formato de dados CSV é exatamente isso: valores separados por vírgula. O arquivo contém linhas e cada linha representa um registro ou entrada. Normalmente, a primeira linha de valores contém os nomes de cada valor separado por vírgula (coluna). As linhas subsequentes contêm os valores propriamente ditos.</p><pre><code>name,age
chris,26
mike,34</code></pre><p>O CSV é legível por humanos, mas há variações desse formato. Às vezes, se os valores contiverem vírgulas (por exemplo, endereços de correspondência), o formato não funcionará como está, de modo que cada valor também é envolvido por aspas. Dessa forma, as vírgulas dentro das aspas são ignoradas e o formato ainda pode funcionar usando apenas as vírgulas fora das aspas para separar os valores.</p><pre><code>"name","age","parents"
"Chris","26","Gregory, Mary"
"Mike","34","David, Sarah"</code></pre><p>Os valores também podem ser separados usando um caractere diferente, como tabulações no lugar de vírgulas.</p><p>Não vamos, porém, nos prender a minúcias. O JSCharting fornece várias ferramentas que ajudam nesse processo e usaremos uma delas para não nos preocuparmos com o formato do arquivo CSV e convertê-lo em JSON (JavaScript Object Notation). O resultado será um array de objetos. Cada objeto representa uma linha com propriedades nomeadas. A primeira linha do arquivo CSV é usada para definir os nomes dessas propriedades.</p><p>Este é o url dos dados nos quais estamos interessados: <a href="https://data.cdc.gov/resource/w9j2-ggv5.csv">https://data.cdc.gov/resource/w9j2-ggv5.csv</a>.</p><p>Você pode clicar para fazer o download e abri-lo no Excel.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-28.png" class="kg-image" alt="image-28" width="479" height="330" loading="lazy"><figcaption>Arquivo CSV aberto no Excel</figcaption></figure><p>No entanto, você fará o download e acessará esses dados CSV em tempo real usando o código JavaScript. O código abaixo pode ser um pouco confuso no início, mas é curto e você pode reutilizá-lo para obter qualquer arquivo CSV, texto ou JSON pela internet de modo programático. É semelhante à antiga tecnologia AJAX, mas muito mais simples de usar.</p><p>Mais uma vez, substitua o conteúdo do arquivo <code>index.js</code> pelo seguinte:</p><pre><code class="language-javascript">fetch('https://data.cdc.gov/resource/w9j2-ggv5.csv')
   .then(function (response) {
      return response.text();
   })
   .then(function (text) {
	csvToSeries(text);
   })
   .catch(function (error) {
      //Something went wrong
      console.log(error);
   });

function csvToSeries(text) {
   console.log(text);
}</code></pre><p>Por que é tão complicado? É porque quando você solicita um arquivo, ele não fica disponível imediatamente. Há um atraso e você precisa aguardar a chegada do arquivo. Portanto, primeiro você solicita o arquivo de outro site usando <code>fetch()</code>.</p><pre><code class="language-javascript">fetch('https://data.cdc.gov/resource/w9j2-ggv5.csv')</code></pre><p>Em seguida, o código dentro da função de argumento <code>then(...)</code> é chamado com a resposta quando ela chega. Essa função converte a resposta em texto e a retorna, que passa o resultado para a próxima função do método <code>then()</code>.</p><pre><code class="language-javascript">.then(function (response) {
	return response.text();
})</code></pre><p>A próxima função do método <code>then(...)</code> chama a função <code>csvToSeries()</code> e passa o texto como argumento.</p><pre><code class="language-javascript">.then(function (text) {
	csvToSeries(text);
})</code></pre><p>Na função do método <code>catch()</code>, você pode especificar o que fazer se algo der errado. Por exemplo, talvez a internet não esteja disponível ou o URL não esteja correto.</p><pre><code class="language-javascript">.catch(function (error) {
	//Something went wrong
	console.log(error);
});</code></pre><p>Nesse caso, o erro é enviado para o console.</p><p>Na função <code>csvToSeries()</code>, passamos esse texto para o console para inspeção.</p><pre><code class="language-javascript">function csvToSeries(text) {
   console.log(text);
}</code></pre><p><strong>Observação<strong>:</strong> </strong>a função <code>fetch()</code> nativa não é compatível com o Internet Explorer 11. Se você também quiser oferecer suporte a esse navegador, poderá usar a função <code>JSC.fetch()</code> que vem com o JSCharting. Ela oferece a mesma funcionalidade, mas acrescenta suporte adicional ao IE11.</p><p>Arraste o arquivo <code>index.html</code> para uma janela do navegador (ou atualize a página se já estiver aberta) e pressione F12. Isso abrirá a janela DevTools do navegador Chrome. Por padrão, a metade inferior da janela do DevTools mostrará a saída do console. É para lá que o texto é enviado quando você executa códigos usando:</p><pre><code class="language-javascript">console.log(text);</code></pre><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/pasted-image-0.png" class="kg-image" alt="pasted-image-0" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/pasted-image-0.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/pasted-image-0.png 858w" width="858" height="278" loading="lazy"><figcaption>Saída da janela do console</figcaption></figure><p>Você também pode colar ou escrever código nessa janela do console para executá-lo. Tente colar todo o trecho de código acima na janela do console (ao lado do caractere &gt;) e pressione Enter. Você perceberá que obtém o mesmo resultado na saída da janela do console. Isso pode ser útil para testar uma linha de código e fazer experimentos.</p><p><strong><strong><strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step3-a.zip">step3-a.zip</a></strong></strong></strong></strong></p><p>Neste ponto, você recuperou o texto do arquivo CSV pela internet e o enviou ao console para provar que ele funciona. Agora podemos começar a trabalhar com ele.</p><p>Vamos dar uma olhada nesse arquivo de dados para ter uma ideia do que há nele: <a href="https://data.cdc.gov/resource/w9j2-ggv5.csv">https://data.cdc.gov/resource/w9j2-ggv5.csv</a></p><p>Usei o Excel para classificar as linhas pela coluna do ano para analisar as linhas de dados de um único ano.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-27.png" class="kg-image" alt="image-27" width="494" height="233" loading="lazy"><figcaption>Os dados do CSV, ordenados por ano.</figcaption></figure><p>Cada ano contém 9 linhas com dados baseados em raça e sexo. Estamos interessados apenas nos valores destacados de homens e mulheres de todas as raças para cada ano. Você criará duas séries com base nas linhas destacadas. Uma série para valores femininos e outra para valores masculinos.</p><p>Agora que você tem uma ideia do que precisa acontecer, vamos começar.</p><p>Primeiro, vamos usar a função <code>JSC.csv2Json()</code> para converter o texto no formato JSON e passá-lo para o console para ver o que ele faz.</p><p>Atualize a função <code>csvToSeries()</code> com o seguinte código:</p><pre><code class="language-javascript">function csvToSeries(text) {
   let dataAsJson = JSC.csv2Json(text);
   console.log(dataAsJson)
}</code></pre><p>Atualize o navegador para ver a saída atualizada do console.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-29.png" class="kg-image" alt="image-29" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-29.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-29.png 859w" width="859" height="356" loading="lazy"><figcaption>Dados do CSV convertidos para JSON usando a função utilitária JSC.csv2Json()</figcaption></figure><p>O console mostra um array de 1062 registros. Este é um desses registros:</p><pre><code class="language-json">{year: 1900, race: "All Races", sex: "Both Sexes", average_life_expectancy: 47.3, mortality: 2518}</code></pre><p><strong>Observação<strong>:</strong></strong> o console pode exibir arrays e objetos para inspeção e você pode expandir e recolher seções no console para explorar detalhes.</p><p>O nome da propriedade <code>average_life_expectancy</code> é um pouco longo, mas você precisará usá-lo. Para evitar digitá-lo mais de uma vez, defina uma constante para armazenar esse nome. Quando você precisar usar essa propriedade, basta escrever o nome da constante <code>lifeExp</code>. Ela terá esta aparência, <code>row[lifeExp]</code>, em vez de <code>row.average_life_expectancy</code>.</p><p>Adicione esta linha na parte superior da função <code>csvToSeries()</code>.</p><pre><code class="language-javascript">function csvToSeries(text) {
	const lifeExp = 'average_life_expectancy';
	...</code></pre><p>Você pode processar esses dados usando JavaScript simples. O resultado final que queremos são duas séries com pontos de dados que incluem um ano e a expectativa de vida para cada ponto.</p><p>Atualize a função <code>csvToSeries()</code> com o seguinte código:</p><pre><code class="language-javascript">function csvToSeries(text) {
	const lifeExp = 'average_life_expectancy';
	let dataAsJson = JSC.csv2Json(text);
	let male = [], female = [];
	dataAsJson.forEach(function (row) {
		 //add either to male, female, or discard.
		console.log(row);
	});
}</code></pre><p>Ele define arrays para pontos de dados masculinos e femininos. Em seguida, ele chama a função array <code>dataAsJson.forEach()</code> passando uma função de retorno de chamada (<em>callback</em>) <code>function(row){...}</code> como argumento. A função <code>forEach()</code> executará a função de retorno de chamada para cada item no array <code>dataAsJson</code>. Por enquanto, chamaremos apenas <code>console.log(row)</code> em cada linha que a função de retorno de chamada encontrar.</p><p>Atualize o navegador e inspecione a saída do console.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/7923058b-f96d-4ba5-b94b-90596f035711.png" class="kg-image" alt="7923058b-f96d-4ba5-b94b-90596f035711" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/7923058b-f96d-4ba5-b94b-90596f035711.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/7923058b-f96d-4ba5-b94b-90596f035711.png 848w" width="848" height="353" loading="lazy"><figcaption>Cada objeto de linha que a função de retorno de chamada encontrou</figcaption></figure><p>Vamos adicionar alguma lógica para filtrar os dados que desejamos e registrar o resultado na janela do console. Substitua a função <code>csvToSeries()</code> por este código.</p><pre><code class="language-javascript">function csvToSeries(text) {
	const lifeExp = 'average_life_expectancy';
	let dataAsJson = JSC.csv2Json(text);
	let male = [], female = [];
	dataAsJson.forEach(function (row) {
		 //add either to male, female, or discard.
		if (row.race === 'All Races') {
			if (row.sex === 'Male') {
				male.push({x: row.year, y: row[lifeExp]});
			} else if (row.sex === 'Female') {
				female.push({x: row.year, y: row[lifeExp]});
			}
		}
	});
    console.log([male, female]);
}</code></pre><p>Dentro da função de retorno de chamada, você decide se a linha é de interesse e a utiliza. Caso contrário, você a descarta.</p><pre><code class="language-javascript">if (row.race === 'All Races') {
	if (row.sex === 'Male') {
		//add data to male array
		male.push({x: row.year, y: row[lifeExp]});
	} else if (row.sex === 'Female') {
		//add data to female array
		female.push({x: row.year, y: row[lifeExp]});
	}
}</code></pre><p>A lógica verifica se o valor <code>row.race</code> é igual a 'All Races'. Se for, verifica se a propriedade <code>row.sex</code> é igual a 'Male' ou 'Female'. Se a linha for igual a qualquer uma delas, ele adiciona os dados aos arrays <code>male</code> ou <code>female</code> como um objeto de ponto <code>{x, y}</code>. Observe o uso da constante <code>lifeExp</code> definida acima, que ajuda a encurtar esse código.</p><p>No final, você usou <code>console.log([male, female])</code> para passar as variáveis <em>male</em> e <em>female</em> (masculino e feminino, em inglês) para o console para inspeção e para garantir que o código funcionou conforme o esperado.</p><p>Depois de atualizar o navegador, o console mostra o resultado, que são dois arrays, cada um com 118 pontos de dados que abrangem os anos de 1900 a 2017.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/pasted-image-0--1-.png" class="kg-image" alt="pasted-image-0--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/pasted-image-0--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/pasted-image-0--1-.png 862w" width="862" height="356" loading="lazy"><figcaption>Os arrays de pontos masculinos e femininos</figcaption></figure><p>Por fim, em vez de passar o resultado para o console, envolva esses pontos de dados em um array de duas séries que o gráfico possa usar diretamente e retorne-os.</p><p>Adicione este código no final da função <code>csvToSeries()</code>:</p><pre><code class="language-javascript">return [
   {name: 'Male', points: male},
   {name: 'Female', points: female}
];</code></pre><p>Se o valor retornado fosse enviado para o console, ele produziria este resultado:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/pasted-image-0--2-.png" class="kg-image" alt="pasted-image-0--2-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/pasted-image-0--2-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/pasted-image-0--2-.png 852w" width="852" height="356" loading="lazy"><figcaption>Dois objetos de série que o gráfico pode consumir diretamente</figcaption></figure><p>Como você pode ver, a lógica para filtrar as linhas é bastante simples e você pode ajustá-la para obter outros detalhes desse conjunto de dados.</p><p>Para saber mais sobre como lidar com arquivos CSV usando os utilitários do JSCharting, consulte este tutorial. Quando você estiver pronto para um tratamento de dados mais avançado, o utilitário JSC.nest() poderá ser usado para criar séries e pontos a partir de dados JSON com muito pouco código.</p><p><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step3-b.zip"><strong><strong>step3-b.zip</strong></strong></a></p><h2 id="passo-4-juntando-tudo"><strong>Passo 4 – </strong>juntando tudo</h2><p>A seção de manipulação de dados foi a etapa mais difícil, mas só ela permitirá que você manipule e extraia dados de interesse de qualquer arquivo CSV. É aqui que tudo se encaixa e que você terá uma sensação de realização.</p><p>Comece adicionando uma função <code>renderChart()</code> ao final do arquivo <code>index.js</code>. Você passará os dados da série para essa função como um argumento.</p><pre><code class="language-javascript">function renderChart(series){
   JSC.Chart('chartDiv', {
      series: series
   });
}</code></pre><p>Na função do método <code>then()</code> que chama a função <code>csvToSeries()</code>, passe o resultado da série para a função <code>renderChart()</code> para ver o que ela desenha no navegador.</p><pre><code class="language-javascript">.then(function (text) {
	let series = csvToSeries(text);
	renderChart(series);
})</code></pre><p><strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step4-a.zip">step4-a.zip</a></strong></strong></p><p>Agora, atualize o navegador. Você deverá ver este gráfico que usa os dados CSV processados na seção anterior. Não é incrível?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/csv-line-chart.png" class="kg-image" alt="csv-line-chart" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/csv-line-chart.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/csv-line-chart.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/csv-line-chart.png 1378w" sizes="(min-width: 720px) 720px" width="1378" height="615" loading="lazy"><figcaption>Gráfico de linhas mostrando dados CSV filtrados</figcaption></figure><p>Uau, o que aconteceu em 1918? A expectativa de vida caiu significativamente lá. De acordo com a Wikipédia, houve uma pandemia de gripe envolvendo o vírus H1N1 que dizimou uma parte da população mundial. Esse evento infeliz mostra como a visualização de dados fornece insights que você normalmente não obteria apenas observando os números.</p><p>Você criou um gráfico usando o tipo de série de linhas padrão e ele está com boa aparência, mas pode fazer alguns ajustes para melhorá-lo ainda mais.</p><p>Primeiro, adicione um título na parte superior para explicar o que o usuário está vendo e uma anotação na parte inferior do gráfico para dar crédito à fonte dos dados. Atualize a função do construtor <code>JSC.Chart()</code> para passar as seguintes opções:</p><pre><code class="language-javascript">function renderChart(series){
	JSC.Chart('chartDiv', {
		title_label_text: 'Life Expectancy in the United States',
		annotations: [{
			label_text: 'Source: National Center for Health Statistics',
			position: 'bottom left'
		}],
		series: series
	});
}
</code></pre><p>Quando você atualiza o navegador, pode ver o gráfico atualizado.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/line-chart-annotations.png" class="kg-image" alt="line-chart-annotations" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/line-chart-annotations.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/line-chart-annotations.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/line-chart-annotations.png 1245w" sizes="(min-width: 720px) 720px" width="1245" height="569" loading="lazy"><figcaption>Gráfico de linhas com título e anotação para atribuição</figcaption></figure><p>Você adicionou uma anotação com texto do rótulo e uma configuração de posição. Também podemos usar outra anotação para o título, mas foi mais fácil usar o rótulo do título neste exemplo.</p><p>É fácil controlar a posição da anotação usando valores como <code>'top right'</code> ou <code>'inside bottom right'</code>. O valor <code>'inside'</code> significa que a anotação é colocada dentro da área do gráfico onde os dados são desenhados. Este <a href="https://jscharting.com/examples/chart-features/annotation/box-positions/">exemplo de gráfico de posições de caixa</a> demonstra todas as opções de configuração de posição.</p><p>A legenda mostra a soma dos valores de pontos de cada série, mas a soma não é importante para esse conjunto de dados. Você pode reduzir as colunas de legenda para mostrar apenas o ícone e o nome da série usando essa configuração:</p><pre><code class="language-javascript">legend_template: '%icon,%name'</code></pre><p>No entanto, você não precisa realmente usar uma legenda. Será mais limpo se simplesmente rotular as próprias linhas. Você pode desativar a legenda e instruir o gráfico a escrever o nome da série no último ponto de cada série de linhas com essas opções de gráfico:</p><pre><code class="language-javascript">legend_visible: false,
defaultSeries_lastPoint_label_text: '&lt;b&gt;%seriesName&lt;/b&gt;',
</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/csv-line-chart-labels.png" class="kg-image" alt="csv-line-chart-labels" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/csv-line-chart-labels.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/csv-line-chart-labels.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/csv-line-chart-labels.png 1393w" sizes="(min-width: 720px) 720px" width="1393" height="571" loading="lazy"><figcaption>Gráfico de linhas usando rótulos de pontos em vez de uma legenda</figcaption></figure><p>O token<code>'%seriesname'</code> é um dos muitos <a href="https://jscharting.com/tutorials/js-chart-labels/token-reference/#point-tokens">tokens relacionados a pontos</a> que podem ser usados em qualquer texto de rótulo de ponto para mostrar detalhes e cálculos de pontos.</p><p>Por fim, vamos ativar a <em>tooltip </em>do eixo x para mostrar a expectativa de vida masculina e feminina em um determinado ano. Em dispositivos móveis, você pode tocar no gráfico para ver a <em>tooltip</em>. Ao usar um PC, a <em>tooltip </em>é exibida ao passar o mouse sobre o gráfico.</p><pre><code class="language-javascript">xAxis_crosshair_enabled: true,</code></pre><p>Você deve estar se perguntando: por que todos esses sublinhados nos nomes das propriedades? Esse não é o nome real da propriedade. É uma forma abreviada de escrever:</p><pre><code class="language-javascript">xAxis: {crosshair: {enabled: true}},</code></pre><p>Você pode achar mais conveniente especificar uma configuração com sublinhados e o JSCharting entenderá o que você quer dizer.</p><p>O texto padrão da <em>tooltip </em>é claro, mas vamos personalizá-lo um pouco para torná-lo nosso.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-60.png" class="kg-image" alt="image-60" width="308" height="203" loading="lazy"><figcaption>Tooltip combinada padrão</figcaption></figure><p>Como <em>tooltip</em> mostra informações sobre cada ponto, o texto é definido nas opções de ponto. A propriedade <code>defaultPoint</code> define as opções de ponto que todos os pontos herdarão automaticamente.</p><pre><code class="language-javascript">defaultPoint_tooltip: '%seriesName &lt;b&gt;%yValue&lt;/b&gt; years',</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-61.png" class="kg-image" alt="image-61" width="342" height="202" loading="lazy"><figcaption>Tooltip personalizada combinada</figcaption></figure><p>Para obter mais informações sobre esse recurso, consulte o <a href="https://jscharting.com/tutorials/js-chart-interactivity/crosshair-combined-tooltip/">tutorial sobre mouse de mira (ponto focal) e <em>tooltip</em></a><em> </em>(texto em inglês).</p><p>Quando você aplicar todas essas opções, seu código será semelhante ao trecho a seguir. Substitua toda a função <code>renderChart()</code> por este código:</p><pre><code class="language-javascript">function renderChart(series){
	JSC.Chart('chartDiv', {
		title_label_text: 'Life Expectancy in the United States',
		annotations: [{
			label_text: 'Source: National Center for Health Statistics',
			position: 'bottom left'
		}],
        legend_visible: false,
		defaultSeries_lastPoint_label_text: '&lt;b&gt;%seriesName&lt;/b&gt;',
		defaultPoint_tooltip: '%seriesName &lt;b&gt;%yValue&lt;/b&gt; years',
		xAxis_crosshair_enabled: true,
		series: series
	});
}
</code></pre><p>Atualize a janela do navegador mais uma vez.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/csv-line-chart-tooltips.png" class="kg-image" alt="csv-line-chart-tooltips" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/csv-line-chart-tooltips.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/csv-line-chart-tooltips.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/csv-line-chart-tooltips.png 1282w" sizes="(min-width: 720px) 720px" width="1282" height="536" loading="lazy"><figcaption>Gráfico de linhas com mouse de mira e tooltip personalizada combinados</figcaption></figure><p>Você conseguiu!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/congratulations.gif" class="kg-image" alt="congratulations" width="444" height="250" loading="lazy"><figcaption>Fonte: giphy.com</figcaption></figure><p>Primeiro, você buscou dados CSV usando JavaScript nativo. Em seguida, você os converteu no formato JSON e filtrou os dados em duas séries. Com essas séries, você criou um belo gráfico de linhas interativo usando o JSCharting e o configurou para ter uma aparência profissional.</p><p>Você pode personalizar e ajustar ainda mais os gráficos para atender às suas necessidades específicas. Visite a seção de <a href="https://jscharting.com/tutorials/">tutoriais</a> para saber mais sobre um tópico específico ou encontre gráficos semelhantes ao que deseja criar na <a href="https://jscharting.com/examples/chart-types/">galeria de exemplos</a> e copie-os para continuar sua jornada de visualização de dados.</p><p>Se tiver problemas ao trabalhar com o JSCharting, sinta-se à vontade para entrar em <a href="https://jscharting.com/support.htm">contato</a> com a equipe de suporte. Eles terão prazer em orientá-lo ou ajudar a resolver qualquer problema que você possa encontrar.</p><p><strong><strong><strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step4-b.zip">step4-b.zip</a></strong></strong></strong></strong></p><h2 id="desafio-adicional"><strong>Desafio adicional</strong></h2><p>Não usamos todos os dados disponíveis nesse arquivo CSV. Vamos fazer experiências com ele para nos divertirmos e praticarmos.</p><p>Crie este gráfico usando o que você aprendeu:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/bonus-trend-line-chart.png" class="kg-image" alt="bonus-trend-line-chart" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/bonus-trend-line-chart.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/bonus-trend-line-chart.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/bonus-trend-line-chart.png 1278w" sizes="(min-width: 720px) 720px" width="1278" height="537" loading="lazy"><figcaption>Desafio: replicar este gráfico por conta própria</figcaption></figure><p>Este arquivo zip contém a resposta:</p><p><strong><strong><a href="https://github.com/arthurPuszynski/first-chart-article/raw/master/zips/step5-bonus.zip">step5-bonus.zip</a></strong></strong></p><p>Você consegue pensar em outros gráficos que pode fazer com esses dados? Continue experimentando e aproveite cada minuto!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tutorial de promises em JavaScript – como concluir ou rejeitar promises em JS ]]>
                </title>
                <description>
                    <![CDATA[ Promises são blocos de construção importantes para operações assíncronas em JavaScript. Você pode pensar que as promises não são tão fáceis de entender, aprender e usar – acredite, você não está sozinho! As promises (em português, promessas) são um desafio para muitos desenvolvedores da Web, mesmo depois de passar anos ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/tutorial-de-promises-em-javascript-como-concluir-ou-rejeitar-promises-em-js/</link>
                <guid isPermaLink="false">6514e8a386ff8703fbd88226</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Filipe Virgínio Vital Torres Barbosa ]]>
                </dc:creator>
                <pubDate>Mon, 13 May 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/cover-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/javascript-promise-tutorial-how-to-resolve-or-reject-promises-in-js/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">JavaScript Promise Tutorial – How to Resolve or Reject Promises in JS</a>
      </p><p><code>Promises</code> são blocos de construção importantes para operações assíncronas em JavaScript. Você pode pensar que as <em>promises</em> não são tão fáceis de entender, aprender e usar – acredite, você não está sozinho!</p><p>As <em>promises</em> (em português, promessas) são um desafio para muitos desenvolvedores da Web, mesmo depois de passar anos trabalhando com elas.</p><p>Neste artigo, quero tentar mudar essa percepção ao compartilhar o que aprendi sobre <em>promises</em> em JavaScript nos últimos anos. Espero que seja útil para você.</p><h1 id="o-que-uma-promise-no-javascript"><strong>O que é uma <em>promise</em> no JavaScript?</strong></h1><p>Uma <code>Promise</code> é um objeto especial no JavaScript. Ela produz um valor após uma operação <code>assícrona</code> (também conhecida como <em>async</em>) ser concluída com êxito, ou um erro se ela não for concluída com sucesso, seja porque excedeu o limite de tempo, por erro de rede etc.</p><p>As conclusões de chamadas bem-sucedidas são indicadas pela chamada da função <code>resolve</code> e os erros são indicados pela chamada da função <code>reject</code>.</p><p>Você pode criar uma <em>promise </em>usando o construtor de <em>promises</em> da seguinte forma:</p><pre><code class="language-js">let promise = new Promise(function(resolve, reject) {    
    // Faz uma chamada assíncrona e conclui ou rejeita essa chamada
});</code></pre><p>Na maioria dos casos, uma <em>promise </em>pode ser usada para uma operação assíncrona. Entretanto, tecnicamente, você pode concluir/rejeitar operações síncronas e assíncronas.</p><h1 id="espere-a-n-o-temos-fun-es-de-callback-para-opera-es-ass-ncronas">Espere aí, não temos funções de<strong> <code>callback</code> </strong>para operações assíncronas<strong>?</strong></h1><p>Sim, está correto. Temos funções de <code>callback</code> no JavaScript. Porém, uma função de <em>callback </em>não é algo especial no JavaScript. É uma função normal que produz resultados após a conclusão de uma chamada <code>assíncrona</code> (com sucesso/erro).</p><p>A palavra "assíncrona" significa que algo acontece no futuro, não agora. Normalmente, <em>callbacks</em> são usadas apenas para fazer coisas como chamadas de rede ou fazer <em>upload</em>/<em>download </em>de coisas, se comunicar com bancos de dados e assim por diante.</p><p>Embora <code>callbacks</code> sejam úteis, elas também têm uma grande desvantagem. Às vezes, podemos ter uma <em>callback</em> dentro de outra <em>callback</em> que está em outra <em>callback</em> e assim por diante. Sério! Vamos entender esse "inferno de callbacks" (do inglês, <em>callback hell</em>) com um exemplo.</p><h2 id="como-evitar-o-inferno-de-callbacks-exemplo-do-pizzahub"><strong>Como evitar o inferno de callbacks – exemplo do PizzaHub</strong></h2><p>Vamos pedir uma pizza Marguerita vegana 🍕 do PizzaHub. Quando fazemos o pedido, o PizzaHub detecta automaticamente nossa localização, encontra uma pizzaria próxima e verifica se a pizza que estamos pedindo está disponível.</p><p>Se estiver disponível, ele detecta que tipo de bebida recebemos gratuitamente junto com a pizza e, por fim, faz o pedido.</p><p>Se o pedido for feito com sucesso, receberemos uma mensagem com uma confirmação.</p><p>Então, como podemos codificar isso usando funções de <em>callback</em>? Eu criei algo parecido com isso:</p><pre><code class="language-js">function pedirPizza(tipo, nome) {
    
    // Consulta a pizzahub por uma loja
    query(`/api/pizzahub/`, function(resultado, erro){
       if (!error) {
           let idLoja = resultado.idLoja;
           
           // Obtém a loja e consulta as pizzas
           query(`/api/pizzahub/pizza/${idLoja}`, function(resultado, erro){
               if (!erro) {
                   let pizzas = resultado.pizzas;
                   
                   // Verifica se minha pizza está disponível
                   let minhaPizza = pizzas.find((pizza) =&gt; {
                       return (pizza.tipo===tipo &amp;&amp; pizza.nome===nome);
                   });
                   
                   // Verifique se há bebidas gratuitas
                   query(`/api/pizzahub/bebidas/${minhaPizza.id}`, function(resultado, erro){
                       if (!erro) {
                           let bebida = resultado.id;
                           
                           // Prepara um pedido
                           query(`/api/pedido`, {'tipo': tipo, 'nome': nome, 'bebida': bebida}, function(resultado, erro){
                              if (!erro) {
                                  console.log(`Seu pedido de ${tipo} ${nome} com ${bebida} foi realizado`);
                              } else {
                                  console.log(`Infelizmente, não temos pizzas para você hoje!`);
                              }
                           });

                       }
                   })
               }
           });
       } 
    });
}

// Chama a função orderPizza
pedirPizza('vegetariana', 'marguerita');</code></pre><p>Vamos dar uma olhada na função <code>pedirPizza</code> no código acima.</p><p>Ela chama uma API para obter o ID da pizzaria mais próxima. Depois disso, obtém a lista de pizzas disponíveis nesse restaurante. Então, ela verifica se a pizza que estamos pedindo foi encontrada e faz outra chamada à API para encontrar as bebidas para essa pizza. Por fim, a API de pedidos faz o pedido.</p><p>Aqui usamos uma <em>callback </em>para cada uma das chamadas de API. Isso nos leva a usar outra <em>callback </em>dentro da anterior, e assim por diante.</p><p>Isso significa que entramos em algo que chamamos (de forma muito expressiva) de <code>Inferno de Callbacks</code>. Ninguém quer isso, certo? Isso também forma uma pirâmide de código que não é apenas confusa, mas também propensa a erros.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/callback-hell.png" class="kg-image" alt="callback-hell" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/callback-hell.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/callback-hell.png 900w" width="900" height="500" loading="lazy"><figcaption>Demonstração do inferno das callbacks e a pirâmide gerada</figcaption></figure><p>Há algumas maneiras de sair do (ou não entrar no) <code>inferno de callbacks</code>. A mais comum é usar uma <code>Promise</code> ou função <code>async</code>. No entanto, para entender bem as funções <code>async</code>, primeiro é preciso ter uma boa compreensão das <code>Promises</code>.</p><p>Portanto, vamos começar e nos aprofundar nas <em>promises</em>.</p><h1 id="entendendo-os-estados-das-promises">Entendendo os estados das<strong> <em>promises</em></strong></h1><p>Apenas para revisar, uma promise pode ser criada com a sintaxe de construtor, dessa maneira:</p><pre><code class="language-js">let promise = new Promise(function(resolve, reject) {
  // Código a ser executado
});</code></pre><p>A função construtora recebe uma função como argumento. Essa função é chamada de <code>função executora</code>.</p><pre><code class="language-js">// Função executora passada como um argumento 
// para o construtor da Promise
function(resolve, reject) {
    // Sua lógica entra aqui...
}</code></pre><p>A função executora recebe dois argumentos: <code>resolve</code> e <code>reject</code>. Essas são as funções de callback fornecidas pela linguagem JavaScript. Sua lógica está dentro da função executora, que é executada automaticamente quando uma <code>new Promise</code> é criada.</p><p>Para que a <em>promise </em>seja eficaz, a função executora deve chamar uma das funções de <em>callback</em>, <code>resolve</code> ou <code>reject</code>. Aprenderemos mais sobre isso em detalhes daqui a pouco.</p><p>O construtor <code>new Promise()</code> retorna um objeto <code>promise</code>. Como a função executora precisa lidar com operações assíncronas, o objeto <em>promise </em>retornado deve ser capaz de informar quando a execução foi iniciada, concluída (<em>resolved</em>) ou retornada com erro (<em>rejected</em>).</p><p>Um objeto <code>promise</code> tem as seguintes propriedades internas:</p><ol><li><code>state</code> – essa propriedade pode ter os seguintes valores:</li></ol><ul><li><code>pending</code> – inicialmente, quando a função executora inicia a execução.</li><li><code>fulfilled</code> – quando a promise é concluída.</li><li><code>rejected</code> – quando a promise é rejeitada.</li></ul><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/states_1.png" class="kg-image" alt="states_1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/states_1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/states_1.png 900w" width="900" height="500" loading="lazy"><figcaption>Estados da <em>promise</em></figcaption></figure><p>2. &nbsp;<code>result</code> – essa propriedade pode ter os seguintes valores:</p><ul><li><code>undefined</code> – inicialmente, quando o valor do <code>state</code> é <code>pending</code>.</li><li><code>value</code> – quando <code>resolve(value)</code> é chamada.</li><li><code>error</code> – quando &nbsp;<code>reject(error)</code> é chamada.</li></ul><p>Essas propriedades internas são inacessíveis ao código, mas podem ser inspecionadas. Isso significa que poderemos inspecionar os valores das propriedades <code>state</code> e <code>result</code> usando a ferramenta de depuração, mas não poderemos acessá-las diretamente usando o programa.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/promise_state_inspect.png" class="kg-image" alt="promise_state_inspect" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/promise_state_inspect.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/promise_state_inspect.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/promise_state_inspect.png 1076w" width="1076" height="595" loading="lazy"><figcaption>É possível inspecionar as propriedades internas de uma <em>promise</em></figcaption></figure><p>O estado de uma <em>promise </em>pode ser <code>pending</code> (pendente), <code>fulfilled</code> (cumprida) ou <code>rejected</code> (rejeitada). Uma <em>promise </em>que é resolvida ou rejeitada é chamada de <code>settled</code> (liquidada).</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/states_2.png" class="kg-image" alt="states_2" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/states_2.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/states_2.png 900w" width="900" height="500" loading="lazy"><figcaption>Uma <em>promise </em>liquidada é cumprida ou rejeitada</figcaption></figure><h3 id="como-as-promises-s-o-conclu-das-e-rejeitadas"><strong>Como as <em>promises </em>são concluídas e rejeitadas</strong></h3><p>Aqui temos um exemplo de uma <em>promise </em>que será concluída imediatamente (estado <code>fulfilled</code>) com o valor <code>Estou pronto</code>.</p><pre><code class="language-js">let promise = new Promise(function(resolve, reject) {
    resolve("Estou pronto");
});</code></pre><p>A <em>promise </em>abaixo será rejeitada (estado <code>rejected</code>) com a mensagem de erro <code>Algo não está correto!</code>.</p><pre><code class="language-js">let promise = new Promise(function(resolve, reject) {
    reject(new Error('Algo não está correto!'));
});</code></pre><p>Um ponto importante a observar:</p><p>Uma função executora de <em>promises </em>deve chamar apenas uma função <code>resolve</code> ou uma função <code>reject</code>. Uma vez que um estado seja alterado (<em>pending</em> =&gt; <em>fulfilled</em> ou <em>pending</em> =&gt; <em>rejected</em>), acabou. Qualquer outra chamada para <code>resolve</code> ou para <code>reject</code> será ignorada.</p><pre><code class="language-js">let promise = new Promise(function(resolve, reject) {
  resolve("Com certeza serei resolvido!");

  reject(new Error('Isso será ignorado?')); // ignorado
  resolve("Ignorado?"); // ignorado
});</code></pre><p>No exemplo acima, apenas o primeiro a ser resolvido será chamado e os demais serão ignorados.</p><h1 id="como-lidar-com-uma-promise-depois-de-cri-la">Como lidar com uma promise depois de criá-la</h1><p>Uma <code>Promise</code> usa uma função executora para concluir uma tarefa (principalmente de maneira assíncrona). Uma função consumidora (que usa um resultado da <em>promise</em>) deve ser notificada quando a função executora concluir (com sucesso) ou rejeitar (com erro).</p><p>Os métodos, <code>.then()</code>, <code>.catch()</code> e <code>.finally()</code>, ajudam a criar o vínculo entre a função executora e as funções consumidoras para que possam estar em sincronia quando uma <em>promise </em>for <code>concluída (resolve)</code> ou <code>rejeitada (reject)</code>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/consumer_executor.png" class="kg-image" alt="consumer_executor" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/consumer_executor.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/consumer_executor.png 900w" width="900" height="500" loading="lazy"><figcaption>Funções executora e consumidora</figcaption></figure><h2 id="como-usar-o-m-todo-then-da-promise"><strong>Como usar o método <code>.then()</code> da <em>promise</em></strong></h2><p>O método <code>.then()</code> deve ser chamado no objeto <em>promise </em>para lidar com um resultado (resolve) ou um erro (reject).</p><p>Aceita duas funções como parâmetros. Normalmente, o método <code>.then()</code> deve ser chamado a partir da função consumidora em que você gostaria de saber o resultado da execução de uma <em>promise</em>.</p><pre><code class="language-js">promise.then(
  (result) =&gt; { 
     console.log(result);
  },
  (error) =&gt; { 
     console.log(error);
  }
);</code></pre><p>Se estiver interessado apenas em resultados bem-sucedidos, pode passar apenas um argumento, desta maneira:</p><pre><code class="language-js">promise.then(
  (result) =&gt; { 
      console.log(result);
  }
);</code></pre><p>Se você estiver interessado apenas no erro, poderá passar <code>null</code> para o primeiro argumento, assim:</p><pre><code class="language-js">promise.then(
  null,
  (error) =&gt; { 
      console.log(error)
  }
);</code></pre><p>No entanto, pode tratar melhor os erros usando o método <code>.catch()</code>, que veremos em um minuto.</p><p>Vamos dar uma olhada em alguns exemplos de tratamento de resultados e erros usando os métodos <code>.then</code> e <code>.catch</code> . Tornaremos esse aprendizado um pouco mais divertido com algumas requisições assíncronas reais. Usaremos a PokeAPI para obter informações sobre Pokémons e concluí-las/rejeitá-las usando <em>promises</em>.</p><p>Primeiro, vamos criar uma função genérica que aceita um URL da PokeAPI como argumento e retorna uma <em>promise</em>. Se a chamada à API for bem-sucedida, uma <em>promise </em>concluída será retornada. Uma <em>promise </em>rejeitada é retornada para qualquer tipo de erro.</p><p>A partir de agora, usaremos essa função em vários exemplos para obter uma <em>promise </em>e trabalhar com ela.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">function getPromise(URL) {
  let promise = new Promise(function (resolve, reject) {
    let req = new XMLHttpRequest();
    req.open("GET", URL);
    req.onload = function () {
      if (req.status == 200) {
        resolve(req.response);
      } else {
        reject("Ocorreu um erro!");
      }
    };
    req.send();
  });
  return promise;
}</code></pre><figcaption>Método utilitário para obter uma <em>promise</em></figcaption></figure><p>Exemplo 1: obter informações de 50 Pokémons:</p><pre><code class="language-js">const ALL_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon?limit=50';

// Já discutimos essa função!
let promise = getPromise(ALL_POKEMONS_URL);

const consumer = () =&gt; {
    promise.then(
        (result) =&gt; {
            console.log({result}); // Exibe o retorno de 50 Pokémons no console do navegador
        },
        (error) =&gt; {
            // Como o URL é válido, isso não será chamado.
            console.log('Encontramos um erro!'); // Exibe um erro no console do navegador
    });
}

consumer();</code></pre><p>Exemplo 2: vamos tentar um URL inválido</p><pre><code class="language-js">const POKEMONS_BAD_URL = 'https://pokeapi.co/api/v2/pokemon-bad/';

// Isso será rejeitado porque o URL retorna erro 404
let promise = getPromise(POKEMONS_BAD_URL);

const consumer = () =&gt; {
    promise.then(
        (result) =&gt; {
            // A promise não foi concluída. Portanto, ela não será executada.
            console.log({result});
        },
        (error) =&gt; {
            // Uma promise rejeitada executará o seguinte
            console.log('We have encountered an Error!'); // Exibe um erro no console do navegador
        }
    );
}

consumer();</code></pre><h2 id="como-usar-o-m-todo-catch-da-promise"><strong>Como usar o método <code>.catch()</code> da <em>promise</em></strong></h2><p>Você pode usar esse método para lidar com erros (rejeições) das <em>promises</em>. A sintaxe de passar <code>null</code> como o primeiro argumento para <code>.then()</code> não é uma boa maneira de tratar erros. Portanto, temos o <code>.catch()</code> para fazer o mesmo trabalho com uma sintaxe simples:</p><pre><code class="language-js">// Isso será rejeitado porque o URL retorna 404
let promise = getPromise(POKEMONS_BAD_URL);

const consumer = () =&gt; {
    promise.catch(error =&gt; console.log(error));
}

consumer();</code></pre><p>Se lançarmos um erro usando <code>new Error("Algo está errado!")</code> em vez de chamar o <code>reject</code> da função executora e dos métodos da <em>promise</em>, ele ainda será tratado como uma rejeição. Isso significa que será capturado pelo método <code>.catch</code>.</p><p>O mesmo se aplica a todas as exceções <em>síncronas</em> que ocorrem no executor da <em>promise </em>e nas funções.</p><p>Aqui está um exemplo onde será tratado como uma rejeição e o método <code>.catch</code> será chamado:</p><pre><code class="language-js">new Promise((resolve, reject) =&gt; {
  throw new Error("Algo está errado!");// Sem chamada rejeitada
}).catch((error) =&gt; console.log(error)); </code></pre><h2 id="como-usar-o-m-todo-finally-da-promise"><strong>Como usar o método <code>.finally()</code> da <em>promise</em></strong></h2><p>O método <code>.finally()</code> realiza tarefas de limpeza como parar um carregamento, fechar uma conexão ativa e assim por diante. O método <code>finally()</code> será chamado independentemente da <em>promise </em>retornar um resultado (<code>resolve</code>) ou um erro (<code>reject</code>). Ele passa o resultado ou o erro para o próximo método, que pode chamar os métodos .then() ou .catch() novamente.</p><p>Aqui temos um exemplo que ajudará você a entender os três métodos juntos:</p><pre><code class="language-js">let loading = true;
loading &amp;&amp; console.log('Carregando...');

// Obtendo a Promise
promise = getPromise(ALL_POKEMONS_URL);

promise.finally(() =&gt; {
    loading = false;
    console.log(`Promessa resolvida e o carregamento é ${loading}`);
}).then((result) =&gt; {
    console.log({result});
}).catch((error) =&gt; {
    console.log(error)
});</code></pre><p>Explicando em detalhes:</p><ul><li>O método <code>.finally()</code> torna o carregamento <code>false</code>.</li><li>Se a <em>promise</em> retornar um resultado (<code>resolve</code>), o método <code>.then()</code> será chamado. Se a <em>promise</em> retornar um erro (<code>reject</code>), o método <code>.catch()</code> será chamado. O <code>.finally()</code> será chamado independentemente do resolve ou do reject.</li></ul><h1 id="o-que-encadeamento-de-promises"><strong>O que é encadeamento de <em>promises</em>?</strong></h1><p>A chamada &nbsp;<code>promise.then()</code> sempre retorna uma <em>promise</em>. Essa <em>promise </em>terá o <code>state</code> como <code>pending</code> e <code>result</code> como <code>undefined</code>. Ela nos permite chamar o próximo método <code>.then</code> em uma nova <em>promise</em>.</p><p>Quando o primeiro método <code>.then</code> retornar um valor, o próximo método <code>.then</code> pode recebê-lo. O segundo pode passar para o terceiro <code>.then()</code> e assim por diante. Isto forma uma cadeia de métodos <code>.then</code> para transmitir as <em>promises</em>. Esse fenômeno é chamado de <code>Cadeia de Promises</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-105.png" class="kg-image" alt="image-105" width="480" height="566" loading="lazy"><figcaption>Cadeia de <em>promises</em></figcaption></figure><p>Aqui está um exemplo:</p><pre><code class="language-js">let promise = getPromise(ALL_POKEMONS_URL);

promise.then(result =&gt; {
    let onePokemon = JSON.parse(result).results[0].url;
    return onePokemon;
}).then(onePokemonURL =&gt; {
    console.log(onePokemonURL);
}).catch(error =&gt; {
    console.log('In the catch', error);
});</code></pre><p>Aqui, primeiro obtemos uma <em>promise </em>resolvida e, em seguida, extraímos o URL para chegar ao primeiro Pokémon. Em seguida, retornamos esse valor e ele será passado como uma <em>promise </em>para a próxima função .then(). Daí o resultado,</p><pre><code class="language-shell">https://pokeapi.co/api/v2/pokemon/1/</code></pre><p>O método <code>.then</code> pode retornar tanto:</p><ul><li>Um valor (já vimos isso)</li><li>Uma nova <em>promise</em>.</li></ul><p>Também pode lançar um erro.</p><p>Aqui está um exemplo em que criamos uma cadeia de <em>promises</em> com os métodos <code>.then</code> que retornam resultados e uma nova <em>promise</em>:</p><pre><code class="language-js">// Promise Chain with multiple then and catch
let promise = getPromise(ALL_POKEMONS_URL);

promise.then(result =&gt; {
    let onePokemon = JSON.parse(result).results[0].url;
    return onePokemon;
}).then(onePokemonURL =&gt; {
    console.log(onePokemonURL);
    return getPromise(onePokemonURL);
}).then(pokemon =&gt; {
    console.log(JSON.parse(pokemon));
}).catch(error =&gt; {
    console.log('In the catch', error);
});</code></pre><p>Na primeira chamada de <code>.then</code>, extraímos o URL e o retornamos como um valor. Esse URL será passado para a segunda chamada <code>.then</code> na qual estamos retornando uma nova <em>promise </em>tendo esse URL como argumento.</p><p>Essa <em>promise </em>será resolvida e passada para a cadeia, onde obteremos as informações sobre o Pokémon. Aqui está o resultado:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-159.png" class="kg-image" alt="image-159" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-159.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/image-159.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-159.png 1382w" sizes="(min-width: 1200px) 1200px" width="1382" height="655" loading="lazy"><figcaption>Resultado da chamada da cadeia de promises</figcaption></figure><p>Caso ocorra um erro ou a rejeição de uma <em>promise</em>, o método .catch da cadeia será chamado.</p><p>Um ponto a ser observado: chamar <code>.then</code> várias vezes não forma uma cadeia de <em>promises</em>. Você pode acabar fazendo algo assim apenas para introduzir um bug no código:</p><pre><code class="language-js">let promise = getPromise(ALL_POKEMONS_URL);

promise.then(result =&gt; {
    let onePokemon = JSON.parse(result).results[0].url;
    return onePokemon;
});
promise.then(onePokemonURL =&gt; {
    console.log(onePokemonURL);
    return getPromise(onePokemonURL);
});
promise.then(pokemon =&gt; {
    console.log(JSON.parse(pokemon));
});
</code></pre><p>Chamamos o método <code>.then</code> três vezes na mesma <em>promise</em>, mas não passamos a <em>promise</em> adiante. Isso é diferente da cadeia de <em>promises</em>. No exemplo acima, o resultado será um erro.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-160.png" class="kg-image" alt="image-160" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-160.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/image-160.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-160.png 1408w" sizes="(min-width: 1200px) 1200px" width="1408" height="105" loading="lazy"></figure><h1 id="como-lidar-com-v-rias-promises">Como lidar com várias <em>promises</em></h1><p>Além dos métodos (.then, .catch e .finally), há seis métodos estáticos disponíveis na API da <em>promise</em>. Os primeiros quatro métodos aceitam um <em>array</em> de <em>promises </em>e as executam em paralelo.</p><ol><li>Promise.all</li><li>Promise.any</li><li>Promise.allSettled</li><li>Promise.race</li><li>Promise.resolve</li><li>Promise.reject</li></ol><p>Vamos examinar cada uma delas.</p><h2 id="o-m-todo-promise-all-"><strong>O método Promise.all()</strong></h2><p><code>Promise.all([promises])</code> aceita uma coleção (por exemplo, um <em>array</em>) de <em>promises </em>como argumento e as executa em paralelo.</p><p>Esse método aguarda a resolução de todas as <em>promises </em>e retorna o array de resultados das <em>promises</em>. Se alguma das <em>promises </em>for rejeitada ou falhar devido a um erro, todos os outros resultados das <em>promises</em> serão ignorados.</p><p>Vamos criar três <em>promises</em> para obter informações sobre três Pokémons.</p><pre><code class="language-js">const BULBASAUR_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon/bulbasaur';
const RATICATE_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon/raticate';
const KAKUNA_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon/kakuna';


let promise_1 = getPromise(BULBASAUR_POKEMONS_URL);
let promise_2 = getPromise(RATICATE_POKEMONS_URL);
let promise_3 = getPromise(KAKUNA_POKEMONS_URL);</code></pre><p>Use o método Promise.all() passando um <em>array</em> de <em>promises</em>.</p><pre><code class="language-js">Promise.all([promise_1, promise_2, promise_3]).then(result =&gt; {
    console.log({result});
}).catch(error =&gt; {
    console.log('An Error Occurred');
});</code></pre><p>Saída:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-161.png" class="kg-image" alt="image-161" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-161.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/image-161.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-161.png 1067w" width="1067" height="165" loading="lazy"></figure><p>Como você pode ver, o resultado de todas as <em>promises</em> é retornado. O tempo para executar todas as <em>promises</em> é igual ao tempo máximo que a <em>promise</em> leva para ser executada.</p><h2 id="o-m-todo-promise-any-"><strong>O método Promise.any()</strong></h2><p><code>Promise.any([promises])</code> – semelhante ao método <code>all()</code>, <code>.any()</code> também aceita um <em>array</em> de <em>promises </em>para executá-las em paralelo. Esse método não espera que todas as <em>promises </em>sejam resolvidas. Ele finaliza quando qualquer uma das promises é resolvida.</p><pre><code class="language-javascript"> Promise.any([promise_1, promise_2, promise_3]).then(result =&gt; {
     console.log(JSON.parse(result));
 }).catch(error =&gt; {
     console.log('An Error Occurred');
 });</code></pre><p>A saída seria o resultado de qualquer uma das <em>promises </em>resolvidas:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-162.png" class="kg-image" alt="image-162" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-162.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/image-162.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-162.png 1373w" sizes="(min-width: 1200px) 1200px" width="1373" height="61" loading="lazy"></figure><h2 id="o-m-todo-promise-allsettled-"><strong>O método Promise.allSettled()</strong></h2><p><code>promise.allSettled([promises])</code> – esse método aguarda que todas as <em>promises </em>sejam resolvidas (resolve/reject) e retorna seus resultados como um <em>array</em> de objetos. Os resultados conterão um estado (fulfilled/rejected) e um valor, se for <em>fulfilled</em>. Em caso de status <em>rejected</em>, ele retornará um motivo para o erro.</p><p>Aqui está um exemplo de todas as <em>promessas</em> cumpridas (<em>fulfilled</em>):</p><pre><code class="language-js">Promise.allSettled([promise_1, promise_2, promise_3]).then(result =&gt; {
    console.log({result});
}).catch(error =&gt; {
    console.log('There is an Error!');
});</code></pre><p>Saída:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-163.png" class="kg-image" alt="image-163" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-163.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/image-163.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-163.png 1600w" sizes="(min-width: 1200px) 1200px" width="1600" height="213" loading="lazy"></figure><p>Se alguma das <em>promises</em> for rejeitada, por exemplo, a promise_1,</p><pre><code class="language-javascript">let promise_1 = getPromise(POKEMONS_BAD_URL);</code></pre><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-164.png" class="kg-image" alt="image-164" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-164.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/image-164.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-164.png 1585w" sizes="(min-width: 1200px) 1200px" width="1585" height="211" loading="lazy"></figure><h2 id="o-m-todo-promise-race-"><strong>O método Promise.race()</strong></h2><p><code>Promise.race([promises])</code> – Aguarda a primeira <em>promise</em> (a mais rápida) ser concluída e retorna o respectivo resultado/erro.</p><pre><code class="language-js">Promise.race([promise_1, promise_2, promise_3]).then(result =&gt; {
    console.log(JSON.parse(result));
}).catch(error =&gt; {
    console.log('An Error Occured');
});</code></pre><p>Retorna a <em>promise </em>que foi resolvida mais rapidamente:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-165.png" class="kg-image" alt="image-165" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/04/image-165.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/04/image-165.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/04/image-165.png 1282w" sizes="(min-width: 1200px) 1200px" width="1282" height="40" loading="lazy"></figure><h2 id="o-m-todo-promise-resolve-reject"><strong>O método Promise.resolve/reject</strong></h2><p><code>Promise.resolve(value)</code> – Ele resolve uma <em>promise </em>com o valor passado. É o mesmo que o seguinte código:</p><pre><code class="language-js">let promise = new Promise(resolve =&gt; resolve(value));</code></pre><p><code>Promise.reject(error)</code> – Rejeita uma <em>promise </em>com o erro passado. É o mesmo que o seguinte código:</p><pre><code class="language-js">let promise = new Promise((resolve, reject) =&gt; reject(error));</code></pre><h1 id="podemos-reescrever-o-exemplo-da-pizzahub-com-promises">Podemos reescrever o exemplo da PizzaHub com <em>promises</em><strong>?</strong></h1><p>Claro, vamos fazer isso. Vamos supor que o método <code>query</code> retornará uma <em>promise</em>. Aqui está um exemplo de método query(). Na vida real, esse método pode se comunicar com um banco de dados e retornar resultados. Nesse caso, ele é bastante codificado, mas tem a mesma finalidade.</p><pre><code class="language-js">function query(endpoint) {
  if (endpoint === `/api/pizzahub/`) {
    return new Promise((resolve, reject) =&gt; {
      resolve({'idLoja': '123'});
    })
  } else if (endpoint.indexOf('/api/pizzahub/pizza/') &gt;=0) {
    return new Promise((resolve, reject) =&gt; {
      resolve({pizzas: [{'tipo': 'vegetariana', 'nome': 'marguerita', 'id': '123'}]});
    })
  } else if (endpoint.indexOf('/api/pizzahub/bebidas') &gt;=0) {
    return new Promise((resolve, reject) =&gt; {
      resolve({id: '10', 'tipo': 'vegetariana', 'nome': 'marguerita', 'bebida': 'coca'});
    })
  } else if (endpoint === `/api/order`) {
    return new Promise((resolve, reject) =&gt; {
      resolve({'tipo': 'vegetariana', 'nome': 'marguerita', 'bebida': 'coca'});
    })
  }
}</code></pre><p>Em seguida, a refatoração do nosso <code>callback hell</code>. Para isso, primeiro criaremos algumas funções lógicas:</p><pre><code class="language-js">// Retorna um id da loja
let getIdLoja = resultado =&gt; resultado.idLoja;

// Retorna uma promise com a lista de pizzas para uma loja
let getListaPizzas = idLoja =&gt; {
  const url = `/api/pizzahub/pizza/${idLoja}`;
  return query(url);
}

// Retorna uma promise com a pizza que combina com o pedido do cliente
let getMinhaPizza = (resultado, tipo, nome) =&gt; {
  let pizzas = resultado.pizzas;
  let minhaPizza = pizzas.find((pizza) =&gt; {
    return (pizza.tipo===tipo &amp;&amp; pizza.nome===nome);
  });
  const url = `/api/pizzahub/bebidas/${minhaPizza.id}`;
  return query(url);
}

// Retorna uma promise depois de fazer o pedido
let fazerPedido = resultado =&gt; {
  let bebida = resultado.id;
   return query(`/api/pedido`, {'tipo': resultado.tipo, 'nome': resultado.nome, 'bebida': resultado.bebida});
}

// Confirma o pedido
let confirmarPedido = resultado =&gt; {
    console.log(`Seu pedido de ${resultado.tipo} ${resultado.nome} com ${resultado.bebida} foi aceito!`);
}</code></pre><p>Use essas funções para criar as <em>promises </em>necessárias. É aqui que você deve comparar com o exemplo do <code>callback hell</code>. Este é bem mais legal e elegante.</p><pre><code class="language-js">function pedirPizza(tipo, nome) {
  query(`/api/pizzahub/`)
  .then(resultado =&gt; getIdLoja(resultado))
  .then(idLoja =&gt; getListaPizzas(idLoja))
  .then(resultado =&gt; getMinhaPizza(resultado, tipo, nome))
  .then(resultado =&gt; realizarPedido(resultado))
  .then(resultado =&gt; confirmarPedido(resultado))
  .catch(function(erro){
    console.log(`Infelimente, não temos pizzas para você hoje!`);
  })
}</code></pre><p>Por fim, chame o método pedirPizza() passando o tipo e o nome da pizza, da seguinte forma:</p><pre><code class="language-js">pedirPizza('vegetariana', 'marguerita');
</code></pre><h1 id="o-que-vem-a-seguir">O que vem a seguir<strong>?</strong></h1><p>Se você chegou até aqui e leu a maior parte das linhas acima, parabéns! Agora você já deve ter uma noção melhor das Promises do JavaScript. Todos os exemplos usados neste artigo estão neste <a href="https://github.com/atapas/js-promise-example">repositório do GitHub</a>.</p><p>Em seguida, você deve aprender sobre a função <code>async</code> no JavaScript, que simplifica ainda mais as coisas. A melhor maneira de aprender o conceito de <em>promises </em>do JavaScript é escrever pequenos exemplos e desenvolvê-los com base neles.</p><p>Independentemente do <em>framework </em>ou da biblioteca (Angular, React, Vue e assim por diante) que usarmos, as operações assíncronas são inevitáveis. Isso significa que precisamos entender as <em>promises </em>para que as coisas funcionem melhor.</p><p>Além disso, tenho certeza de que você achará o uso do método <code>fetch</code> muito mais fácil agora:</p><pre><code class="language-js">fetch('/api/user.json')
.then(function(response) {
    return response.json();
})
.then(function(json) {
    console.log(json); // {"name": "tapas", "blog": "freeCodeCamp"}
});</code></pre><ul><li>O método <code>fetch</code> retorna uma <em>promise</em>. Portanto, podemos chamar o método <code>.then</code> nele.</li><li>O restante é sobre a cadeia de <em>promises </em>que aprendemos neste artigo.</li></ul><h1 id="antes-de-terminarmos-">Antes de terminarmos<strong>...</strong></h1><p>Obrigado por ler até aqui! Vamos nos conectar. Você pode me mandar mensagens no Twitter<a href="https://twitter.com/tapasadhikary"> (@tapasadhikary)</a> com comentários.</p><p>Você também pode gostar destes artigos (em inglês):</p><ul><li><a href="https://blog.greenroots.info/javascript-undefined-and-null-lets-talk-about-it-one-last-time-ckh64kmz807v848s15kdkg3dd">JavaScript undefined and null: Let's talk about it one last time!</a></li><li><a href="https://blog.greenroots.info/javascript-equality-comparison-with-and-objectis-ckdpt2ryk01vel9s186ft8cwl">JavaScript: Equality comparison with ==, === and Object.is</a></li><li><a href="https://www.freecodecamp.org/news/javascript-this-keyword-binding-rules/">The JavaScript `this` Keyword + 5 Key Binding Rules Explained for JS Beginners</a></li><li><a href="https://www.freecodecamp.org/news/javascript-typeof-how-to-check-the-type-of-a-variable-or-object-in-js/">JavaScript TypeOf – How to Check the Type of a Variable or Object in JS</a></li></ul><p>Isso é tudo por enquanto. Voltaremos a nos ver em breve com meu próximo artigo. Até lá, cuide-se bem. 🙂</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como a mineração de Bitcoin realmente funciona ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Subhan Nadeem À medida que o Bitcoin é amplamente adotado e reconhecido, seu modelo de segurança fundamental, conhecido como mineração, é posto sob os holofotes e examinado mais e mais a cada dia. As pessoas estão cada vez mais preocupadas com o impacto ambiental da mineração de Bitcoin ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-a-mineracao-de-bitcoin-realmente-funciona/</link>
                <guid isPermaLink="false">65034c4fade67a03f81e4a1f</guid>
                
                    <category>
                        <![CDATA[ Bitcoin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Filipe Virgínio Vital Torres Barbosa ]]>
                </dc:creator>
                <pubDate>Tue, 02 Apr 2024 01:34:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/0_A8uxgOGZV8XlHg8s.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-bitcoin-mining-really-works-38563ec38c87/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How Bitcoin mining really works</a>
      </p><p>Escrito por: Subhan Nadeem</p><p>À medida que o Bitcoin é amplamente adotado e reconhecido, seu modelo de segurança fundamental, conhecido como mineração, é posto sob os holofotes e examinado mais e mais a cada dia.</p><p>As pessoas estão cada vez mais preocupadas com o impacto ambiental da mineração de Bitcoin e interessadas no assunto, na segurança e no grau de descentralização do seu modelo subjacente e até no impacto potencial de uma descoberta da computação quântica no futuro dos Bitcoins e de outras criptomoedas.</p><p>Muitas vezes, a prova de trabalho é descrita como um "quebra-cabeças criptográfico", mas o que é de fato este quebra-cabeças?</p><p>Para compreender de fato essas questões (e quaisquer respostas possíveis), é preciso entender a mineração de Bitcoin em si e da sua evolução.</p><p>Este artigo tratará de todos os componentes técnicos e elementos da prova de trabalho e de como eles se mantém em perfeita sincronia, fazendo com que o Bitcoin seja a plataforma descentralizada que é hoje.</p><h3 id="por-que-a-minera-o-funciona-hashing-criptogr-fico-unidirecional">Por que a mineração funciona: hashing criptográfico unidirecional</h3><p>A <em>blockchain </em>do Bitcoin é frequentemente descrita como um banco de dados que é criptograficamente seguro e, subsequentemente, imutável. A tecnologia que alimenta essa imutabilidade e segurança é o <strong>hashing criptográfico</strong>.</p><p>Uma função de <em>hash </em>criptográfico é uma função matemática que, de maneira simples, pega qualquer dado inserido e o converte para uma sequência de caracteres de tamanho fixo.</p><p>No entanto, existem quatro características especiais dessas funções que as tornam inestimáveis para a rede dos Bitcoins. São elas:</p><ol><li><strong>Determinística</strong> <strong><strong>— </strong></strong>para qualquer entrada na função <em>hash</em> criptográfica, a saída resultante será sempre a mesma;</li><li><strong>Rápida</strong> <strong>—</strong> computar a saída da função <em>hash</em>, dada qualquer entrada, é um processo relativamente rápido (não precisa de computação pesada);</li><li><strong>Exclusividade<strong> — </strong></strong>cada entrada na função deve resultar em uma saída completamente aleatória e exclusiva (em outras palavras, não há duas entradas que resultem na mesma saída);</li><li><strong><strong>Irrevers</strong>ível<strong> — </strong></strong>a partir de uma saída de uma função <em>hash</em>, a entrada original não pode ser obtida.</li></ol><p>Essas regras formam a base que permite à mineração de Bitcoins proteger a rede.</p><p>O criador do protocolo Bitcoin, Satoshi Nakomoto, escolheu usar em particular a <a href="https://pt.wikipedia.org/wiki/SHA-2">função hash SHA-256</a> como base para a mineração de Bitcoins. Essa é uma função de hash criptográfico específica, que foi comprovada matematicamente para atender às propriedades acima. Ela produz sempre um <strong>número de 256 bits</strong> (a unidade mais básica de computação), que é normalmente representado no sistema numérico hexadecimal com 64 caracteres para facilitar a leitura humana.</p><p>A saída da função SHA-256 é normalmente referida como o <strong><em>hash</em></strong> da sua entrada.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/1iObT23KZMg-OPHVKyPW3Fp-12cFhc2oaMdI.png" class="kg-image" alt="1iObT23KZMg-OPHVKyPW3Fp-12cFhc2oaMdI" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/1iObT23KZMg-OPHVKyPW3Fp-12cFhc2oaMdI.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/1iObT23KZMg-OPHVKyPW3Fp-12cFhc2oaMdI.png 800w" sizes="(min-width: 720px) 720px" width="800" height="541" loading="lazy"><figcaption>Uma entrada para uma função <em>hash</em> resulta numa saída totalmente única</figcaption></figure><p>Abaixo, temos um exemplo de entrada e saída de uma função SHA-256 (você mesmo pode experimentá-la <a href="http://www.xorbin.com/tools/sha256-hash-calculator">aqui</a>):</p><pre><code>Entrada do SHA-256:
&lt;Transação de Bitcoins&gt;
Saída do SHA-256:
77077b1f4c3ad44c83dc0bdb8d937e9b71c0ef07a35c2664bb7da85be738eacf</code></pre><p>Curiosamente, na maioria dos lugares onde o <em>hashing</em> é usado no protocolo Bitcoin, o <strong><em>hashing</em> duplo</strong> é usado. Isso significa que a saída original da função SHA-256 é então colocada de volta na função SHA-256 para obter outra saída. Segue abaixo como seria esse processo:</p><pre><code>Entrada do SHA-256 (primeiro passo):
&lt;Transação de Bitcoins&gt;
Saída (primeiro passo):
77077b1f4c3ad44c83dc0bdb8d937e9b71c0ef07a35c2664bb7da85be738eacf

Entrada do SHA-256 (segundo passo):
77077b1f4c3ad44c83dc0bdb8d937e9b71c0ef07a35c2664bb7da85be738eacf
Saída (segundo passo e resultado final):
3c6c55b0e4b607b672b50f04e028a6951aed6dc97b91e103fb0f348c3f1dfa00</code></pre><p>O <em>hashing </em>duplo é utilizado para proteção contra ataques de aniversário. Um ataque de aniversário é um cenário em que o agressor é capaz de produzir o mesmo <em>hash </em>que outra entrada, só que usando uma entrada completamente diferente (chamada de <strong>colisão</strong>). Isso quebra a terceira propriedade, da <strong>exclusividade</strong>. Sem ela, dois blocos de Bitcoin completamente diferentes podem ser representados exatamente pelo mesmo <em>hash</em>, permitindo que os agressores troquem os blocos.</p><p>Com a função SHA-256, a probabilidade de esse ataque acontecer é infinitamente pequena. Se não fosse quase impossível, o SHA-256 seria considerado quebrado.</p><p>Contudo, outras funções de <em>hash </em>foram "quebradas" no passado. Para evitar que isso aconteça com o SHA-256 no futuro (e efetivamente quebrar o modelo de segurança do Bitcoin) é melhor fazer o <strong>hash </strong>do<strong> hash</strong>. Isso reduz pela metade a probabilidade de ocorrer uma colisão, tornando o protocolo muito mais seguro.</p><p>De maneira simplificada, a mineração de Bitcoin é um sistema no qual todas as transações de Bitcoin são enviadas para os mineradores de Bitcoin. Os mineradores selecionam transações no valor de um megabyte, agrupam-nas como entrada na função SHA-256 e tentam encontrar um resultado específico que a rede aceite. O primeiro minerador a encontrar esse resultado e publicar o bloco na rede recebe uma recompensa na forma de taxas de transação e criação de novos Bitcoins.</p><p>Vamos dar um passo adiante e mergulhar na própria <em>blockchain </em>do Bitcoin para ver o que exatamente os mineradores fazem para tornar a rede segura.</p><h3 id="minera-o-de-bitcoins-uma-introdu-o-t-cnica"><strong>Mineração de bitcoins: uma introdução técnica</strong></h3><p>A mineração foi introduzida como a solução para o problema do gasto duplo. Se eu tiver 1 Bitcoin e enviá-lo para Bob e depois tentar enviar o mesmo Bitcoin para Alice, a rede garante que apenas uma transação será aceita. Isso é feito pelo processo de mineração.</p><p>Antes de mergulhar nos detalhes técnicos, é importante entender por que a mineração é necessária para proteger a rede. A moeda fiduciária que existe atualmente é criada e validada por um banco central. Como o Bitcoin opera sob a rígida premissa de descentralização e consenso, não pode haver nenhuma autoridade central que valide e marque a emissão dessa moeda, bem como a validação de quaisquer transações que ocorram com essa moeda.</p><p>Satoshi Nakamoto propôs a única solução conhecida na época para resolver esse problema de validação na forma de um sistema orientado por consenso. Intitulado no <em>whitepaper </em>do Bitcoin como <strong>proof-of-work</strong> (prova de trabalho), esse esquema justifica de modo elegante que as transações são validadas por aqueles que estão dispostos a gastar energia física computacional e tempo suficientes para fazê-lo, ao mesmo tempo em que introduz um incentivo para induzir a concorrência no mercado. Essa concorrência permite que a descentralização surja e prospere organicamente no ecossistema.</p><h3 id="uma-olhada-dentro-do-bloco"><strong>Uma olhada dentro do bloco</strong></h3><p>Um bloco de Bitcoin consiste basicamente em dois componentes:</p><h4 id="1-transa-es-na-forma-de-uma-rvore-de-merkle"><strong>1. </strong>Transações, na forma de uma árvore de Merkle</h4><p>Os computadores de mineração coletam transações suficientes para preencher um bloco e as agrupam em uma árvore de Merkle.</p><p>Uma árvore de Merkle é um conceito relativamente simples: as transações ficam na parte inferior da árvore como folhas e são criptografadas em um <em>hash </em>usando a função SHA-256. A combinação de duas transações de folha é criptografada novamente em um <em>hash </em>usando a função SHA-256 para formar um pai dessas folhas. Esse pai é continuamente criptografado em <em>hash </em>para cima, combinado com outros pais, até que uma única <strong>raiz</strong> seja criada. O <em>hash </em>dessa raiz é efetivamente uma representação única das transações que estão abaixo dela.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/3Y5SmuCwRz8GnPlpMVo9SUG0n3mg95o4fwoP.png" class="kg-image" alt="3Y5SmuCwRz8GnPlpMVo9SUG0n3mg95o4fwoP" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/3Y5SmuCwRz8GnPlpMVo9SUG0n3mg95o4fwoP.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/3Y5SmuCwRz8GnPlpMVo9SUG0n3mg95o4fwoP.png 800w" sizes="(min-width: 720px) 720px" width="800" height="397" loading="lazy"><figcaption>Uma visualização de como uma árvore de Merkle é construída - as folhas na parte inferior da árvore são transações</figcaption></figure><p>A raiz da árvore de Merkle é uma combinação dos <em>hashes </em>de cada transação na árvore.</p><p>Lembre-se que, para qualquer entrada em uma função de <em>hash</em>, a saída é totalmente <strong>exclusiva</strong>. Portanto, quando a maioria dos nós da rede recebe um bloco minerado, o <em>hash </em>da raiz da árvore de Merkle atua como um resumo imutável de todas as transações nesse determinado bloco.</p><p>Se alguém mal-intencionado tentasse alterar o conteúdo de uma transação em um bloco, seu <em>hash </em>seria alterado. Essa alteração de um <em>hash </em>seria propagada pela árvore de Merkle da transação até que o <em>hash </em>da raiz fosse alterado. Qualquer nó pode então detectar rapidamente esse ato malicioso comparando a raiz da árvore de Merkle do bloco alterado com a árvore de Merkle de um bloco válido.</p><h4 id="2-o-cabe-alho-do-bloco"><strong>2. O cabeçalho do bloco</strong></h4><p>O cabeçalho do bloco é um resumo do conteúdo do próprio bloco. Ele contém os <strong>seis componentes</strong> a seguir:</p><ul><li>A versão do software que o cliente Bitcoin está executando;</li><li>O registro de data e hora do bloco;</li><li>A raiz da árvore de Merkle com as transações contidas;</li><li>O <em>hash </em>do bloco anterior;</li><li>Um <strong><strong>nonce</strong></strong> (número aleatório que pode ser usado apenas uma vez);</li><li>O <strong>target </strong>ou destino.</li></ul><p>Lembre-se de que a raiz da árvore de Merkle de transações funciona como um resumo eficaz de cada transação no bloco, sem a necessidade de examinar cada transação.</p><p>O <em>hash </em>do bloco anterior permite que a rede coloque corretamente o bloco em ordem cronológica. É daí que deriva o termo <strong>blockchain</strong> - cada bloco é encadeado a um bloco anterior.</p><p>O <strong>nonce</strong> e o <strong>target</strong> fazem a mineração funcionar. Eles são a base para resolver o quebra-cabeça SHA-256 que os mineradores precisam resolver.</p><p>Observe que todos esses dados no cabeçalho do bloco são compactados em 80 bytes usando uma notação chamada <em>little-endian</em>, o que torna a transferência de cabeçalhos de bloco entre os nós um processo trivialmente eficiente. Para essa explicação, ignoraremos essa compactação e assumiremos que os dados estão em sua forma original.</p><h3 id="explicando-o-problema-da-minera-o"><strong>Explicando o problema da mineração</strong></h3><p>O <strong>target</strong> armazenado no cabeçalho do bloco é simplesmente um valor numérico armazenado em bits. Na notação tradicional de base 10, esse <em>target </em>varia de 0 a algum lugar na faixa de 2²²⁴ (um número com <strong>mais de 67 dígitos</strong>), dependendo de quantos mineradores estão competindo para resolver esse problema ao mesmo tempo.</p><p>Lembre-se de que o resultado do SHA-256 é apenas um número. O objetivo de um minerador é pegar o cabeçalho do bloco atual, adicionar um número aleatório a ele chamado <strong>nonce</strong> e calcular seu <em>hash</em>. Esse valor numérico do <em>hash </em>deve ser menor que o valor do <em>target</em>.</p><p>Isso é tudo o que há para fazer, mas é muito mais fácil falar do que fazer.</p><p>Lembre-se da primeira propriedade do SHA-256: uma entrada em uma função de <em>hash </em>sempre resultará na mesma saída. Portanto, se o minerador pegasse o cabeçalho do bloco, fizesse o <em>hash </em>e percebesse que o valor do <em>hash </em>não era menor do que a meta, ele teria que alterar a entrada de algum modo para tentar encontrar um <em>hash </em>abaixo do valor do <em>target</em>.</p><p>É aí que entra o <strong>nonce</strong>.</p><p>O minerador adiciona um número (a partir de 0), chamado <strong>nonce</strong>, ao cabeçalho do bloco e faz o <em>hash </em>desse valor. Se o valor do <em>hash </em>não for menor do que o <em>target</em>, o minerador incrementará o <em>nonce </em>em 1, o adicionará novamente ao cabeçalho do bloco e fará o <em>hash </em>desse valor alterado. Esse processo é repetido continuamente até que seja encontrado um <em>hash </em>menor que o valor do <em>target</em>.</p><h4 id="um-exemplo-de-minera-o">Um exemplo de mineração</h4><p>Aqui está uma aproximação grosseira do que compõe o cabeçalho do primeiro bloco:</p><ul><li>A raiz de Merkle da transação no bloco Genesis:</li></ul><pre><code>Raiz de Merkle:
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b</code></pre><ul><li>A primeira versão conhecida do Bitcoin: <code>0.1.0</code></li><li>O registro de data e hora do bloco: <code>2009–01–03 18:15:05</code></li><li>O <em>target </em>(esse também é o valor mais alto que o <em>target </em>poderá atingir):</li></ul><pre><code>Target:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</code></pre><ul><li>Nenhum <em>hash </em>de bloco anterior – esse foi o primeiro bloco e, portanto, esse é um caso único</li></ul><p>O cabeçalho final do bloco após a adição de seus componentes:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/RgFYX1FSetNk-EJF91HSNTcVhqIYyDziZJkD.png" class="kg-image" alt="RgFYX1FSetNk-EJF91HSNTcVhqIYyDziZJkD" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/RgFYX1FSetNk-EJF91HSNTcVhqIYyDziZJkD.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/RgFYX1FSetNk-EJF91HSNTcVhqIYyDziZJkD.png 767w" sizes="(min-width: 720px) 720px" width="767" height="672" loading="lazy"><figcaption>Os dados do bloco Genesis (isso inclui o nonce, mas vamos fingir que não), fonte: <a href="https://bitcointalk.org/index.php?topic=52706" rel="noopener">bitcointalk</a></figcaption></figure><p>Vamos pegar esse grande cabeçalho e calcular o <em>hash </em>duplo:</p><pre><code>SHA-256 do cabeçalho:
7d80bd12dfdccbdde2c41c9f406edfc05afb3320f5affc4f510b05a3394e1c91

SHA-256 do resultado anterior (resultado final):
c5aa3150f61b752c8fb39525f911981e2f9982c8b9bc907c73914585ad2ef12b</code></pre><p>Tanto o <em>hash </em>de destino quanto o de saída são números incrivelmente grandes quando convertidos para a base 10 (lembre-se: mais de 67 dígitos). Em vez de tentar demonstrar a comparação dos dois aqui, a função Python a seguir trata da comparação:</p><pre><code>def isBlockHashLessThanTarget(blockHash, target):
    return int(blockHash, 16) &lt; int(target, 16)</code></pre><p>Será retornado verdadeiro se o <em>hash </em>for menor do que o destino; caso contrário, falso.</p><p>Aqui está o resultado do nosso <em>target </em>e do <em>hash </em>de bloco:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/mI97AvtxoLFh08Qy99YmpOesirwiyS3a6iLj.png" class="kg-image" alt="mI97AvtxoLFh08Qy99YmpOesirwiyS3a6iLj" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/mI97AvtxoLFh08Qy99YmpOesirwiyS3a6iLj.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/mI97AvtxoLFh08Qy99YmpOesirwiyS3a6iLj.png 800w" sizes="(min-width: 720px) 720px" width="800" height="158" loading="lazy"></figure><p>Agora, pegamos o valor hexadecimal do bloco original e adicionamos 1 a ele. O resultado é o seguinte:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/M7hXm9TXd9CFp3vmZ4sOUHxyvuzMHowjTifh.png" class="kg-image" alt="M7hXm9TXd9CFp3vmZ4sOUHxyvuzMHowjTifh" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/M7hXm9TXd9CFp3vmZ4sOUHxyvuzMHowjTifh.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/M7hXm9TXd9CFp3vmZ4sOUHxyvuzMHowjTifh.png 752w" sizes="(min-width: 720px) 720px" width="752" height="662" loading="lazy"><figcaption>Observe como o último dígito agora é 1, devido à adição do nonce</figcaption></figure><p>Em seguida, executamos o mesmo algoritmo de <em>hashing </em>e a comparação com esses dados alterados. Se não estiverem abaixo do <em>target</em>, continue repetindo.</p><p>Quando um <em>hash </em>bem-sucedido é encontrado, o último <em>nonce </em>usado para encontrar essa solução é salvo no bloco.</p><p>O <em>nonce </em>listado no bloco Genesis é 2.083.236.893.</p><p>Isso significa que Satoshi Nakomoto iterou esse processo mais de 2 bilhões de vezes antes de encontrar o <em>hash </em>correto.</p><p>Escrevi uma pequena implementação em Python desse processo de mineração de blocos do Genesis, que pode ser encontrada no meu <a href="https://github.com/subhan-nadeem/bitcoin-mining-python">GitHub</a>.</p><p>Veja quanto tempo levaria para você minerar com sucesso o bloco Genesis!</p><h4 id="uma-advert-ncia-extranonce">Uma advertência:<strong> <code>extraNonce</code></strong></h4><p>O valor do <em>nonce </em>em um cabeçalho de bloco é armazenado como um número de 32 bits. Isso significa que o <em>nonce </em>mais alto que alguém pode obter é 2³² (aproximadamente 4 bilhões). Após 4 bilhões de iterações, o <em>nonce </em>se esgota e, se não for encontrada uma solução, os mineradores ficam empacados mais uma vez.</p><p>A solução para isso é adicionar um campo à <strong>coinbase </strong>(o conteúdo da transação de um bloco, armazenado como a árvore de Merkle) chamado <strong>extraNonce</strong>. O tamanho desse extraNonce é limitado apenas pelo tamanho do próprio bloco e, portanto, pode ser tão grande quanto os mineradores desejarem, desde que o tamanho do bloco esteja dentro dos limites do protocolo.</p><p>Se todos os 4 bilhões de valores possíveis do <em>nonce </em>forem esgotados, o <strong>extraNonce</strong> será adicionado e incrementado na <strong>coinbase</strong>. Uma nova raiz da árvore de Merkle e, subsequentemente, um novo cabeçalho de bloco são calculados, e o <strong>nonce</strong> é iterado mais uma vez. Esse processo é repetido até que um <em>hash </em>adequado seja encontrado.</p><p>É melhor evitar adicionar o <strong>extraNonce</strong> até que o <strong>nonce</strong> se esgote, pois qualquer alteração no extraNonce altera a árvore de Merkle. Isso requer computação adicional para propagar a alteração para cima até que uma nova raiz da árvore de Merkle seja calculada.</p><h4 id="a-recompensa-do-minerador"><strong>A recompensa do minerador</strong></h4><p>O minerador que conseguir publicar um bloco mais rápido é recompensado com um Bitcoin novinho em folha, criado do nada. Atualmente, essa recompensa é de 12,5 BTC. Como esses Bitcoins surgem?</p><p>Cada minerador simplesmente adiciona uma nova transação de saída ao seu bloco que atribui 12,5 Bitcoins a si mesmo antes de começar a minerar o bloco. O protocolo da rede aceitará essa transação especial como válida ao receber um bloco recém-validado. Essa transação especial é chamada de <strong>transação de geração</strong>.</p><p>É responsabilidade do minerador adicionar essa transação ao bloco antes de minerá-lo. Houve, pelo menos, um caso em que os mineradores se esqueceram de adicionar a recompensa à transação antes de minerar um bloco, literalmente destruindo 12,5 BTC!</p><h3 id="validando-a-prova-de-trabalho"><strong>Validando a prova de trabalho</strong></h3><p>Digamos que nosso minerador tenha encontrado um <em>hash </em>que seja menor que o <em>target</em>. Tudo o que esse minerador precisa fazer é publicar o bloco minerado com os seis componentes originais em qualquer nó conectado.</p><p>Esse nó que recebe o bloco verificará primeiro o conjunto de transações, garantindo que todas as transações sejam válidas (por exemplo, todas as transações estão devidamente assinadas e as moedas não estão sendo gastas duas vezes e/ou criadas do nada).</p><p>Em seguida, ele apenas gerará o <strong>duplo hash</strong> do cabeçalho do bloco e garantirá que o valor esteja abaixo do valor do <em>target </em>incluído no bloco. Quando o bloco for considerado válido, o novo nó continuará a propagar esse bloco pela rede até que todos os nós tenham um registro atualizado.</p><p>Como você pode ver, os blocos recém-publicados podem ser facilmente verificados por qualquer nó. Entretanto, a publicação de um bloco válido na rede requer uma quantidade incrivelmente grande de poder computacional (portanto, eletricidade e tempo). Essa assimetria é o que permite que a rede seja protegida e, ao mesmo tempo, permite que os indivíduos que desejam realizar atividades econômicas na rede o façam de maneira relativamente simples.</p><h3 id="o-tempo-de-produ-o-de-blocos-e-o-ajuste-do-target">O tempo de produção de blocos e o ajuste do <em>target</em></h3><p>Quando os primeiros mineradores começaram a minerar, cada um deles monitorou o <strong>tempo de produção de blocos</strong>. Cada bloco de Bitcoin tem um tempo de produção de blocos definido de 10 minutos. Isso significa que, dado o nível atual de capacidade computacional na rede (<strong>hashrate </strong>da rede), os nós sempre esperam que novos blocos validados sejam produzidos a cada 10 minutos, em média.</p><p>É razoável esperar que os blocos sejam produzidos em 10 minutos porque a probabilidade de encontrar um bloco, considerando o <em>hashrate </em>da rede, é conhecida.</p><p>Por exemplo, vamos pegar o alvo mais fácil que já existiu no Bitcoin: o bloco de Genesis. A probabilidade de um único <em>hash </em>ser menor do que o <em>target </em>mais fácil é de 1 em 2³². Isso é um em mais de quatro bilhões. Portanto, é razoável esperar que alguém execute 2³² iterações do problema de mineração para encontrar um <em>hash </em>adequado. Os nós da rede esperavam que quatro bilhões dessas iterações fossem executadas por <strong>todos</strong> os mineradores da rede a cada 10 minutos.</p><p>Se, em uma amostra grande de blocos, os blocos começarem a aparecer mais rápido do que 10 minutos, essa é uma indicação bastante clara de que os nós da rede estão iterando por quatro bilhões de <em>hashes </em>muito mais rápido do que 10 minutos. Essa situação faz com que cada nó ajuste o <em>target </em>proporcionalmente com base no aumento (ou diminuição) da potência da rede para garantir que os blocos continuem sendo produzidos a cada 10 minutos.</p><p>Na realidade, os nós da rede monitoram o tempo de produção de blocos em <strong>2016</strong> blocos, o que equivale a exatamente duas semanas. A cada duas semanas, o tempo total de produção de blocos é comparado com o tempo de produção de blocos esperado (que é de 20160 minutos).</p><p>Para obter o novo <em>target</em>, basta multiplicar o <em>target </em>existente pela proporção do tempo total de produção de blocos real nas últimas duas semanas para obter o tempo de produção de blocos esperado. Isso ajustará o <em>target </em>proporcionalmente à quantidade de poder computacional que entra ou sai da rede.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/M3-52KmmkeyZCRECDfzfdACTrILXpveYlDn5.png" class="kg-image" alt="M3-52KmmkeyZCRECDfzfdACTrILXpveYlDn5" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/M3-52KmmkeyZCRECDfzfdACTrILXpveYlDn5.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/M3-52KmmkeyZCRECDfzfdACTrILXpveYlDn5.png 800w" sizes="(min-width: 720px) 720px" width="800" height="91" loading="lazy"><figcaption>Fórmula para calcular o novo <em>target</em>, executada a cada 20160 minutos (duas semanas) por cada nó de Bitcoin</figcaption></figure><p>O tempo de produção de blocos e a capacidade de calcular facilmente a probabilidade de encontrar um bloco válido permitem que os nós monitorem e determinem facilmente o <em>hashpower </em>total na rede e ajustem a rede. Independentemente da quantidade de potência de computacional adicionada à rede ou da rapidez com que é adicionada, em média, o tempo de produção de blocos sempre permanecerá em 10 minutos.</p><p>A taxa de <em>hash </em>total atual na rede é de 28,27 <em>exahash</em> por segundo. Isso significa que <strong>28,27 x 10¹⁸</strong> <em>hashes </em>são executados a cada segundo em todos os computadores da rede.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/d9dUC5kBAfoDhYFAhuUIF-49pjPT-risoGxB.png" class="kg-image" alt="d9dUC5kBAfoDhYFAhuUIF-49pjPT-risoGxB" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/d9dUC5kBAfoDhYFAhuUIF-49pjPT-risoGxB.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/d9dUC5kBAfoDhYFAhuUIF-49pjPT-risoGxB.png 800w" sizes="(min-width: 720px) 720px" width="800" height="450" loading="lazy"></figure><h3 id="resumindo">Resumindo</h3><p>Aqui, cobrimos de maneira abrangente o seguinte:</p><ul><li>Por que o <em>hashing </em>criptográfico unidirecional é vital para a prova de trabalho;</li><li>Um detalhamento da construção de um bloco de Bitcoin;</li><li>O processo de mineração real e a iteração em si;</li><li>Como os nós podem validar facilmente outros blocos;</li><li>Como a rede consegue manter o algoritmo e a competitividade monitorando o tempo de bloqueio e ajustando o <em>target</em>.</li></ul><p>Agora, você deve ser capaz de entender e explicar como a prova de trabalho realmente funciona e por que ela é considerada um algoritmo totalmente seguro que permite a descentralização e o consenso!</p><p><strong>Siga o autor no <a href="https://twitter.com/SubhanNadeem19">Twitter</a> e no Medium se estiver interessado em artigos mais detalhados e informativos como esses no futuro!</strong></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
