One place for hosting & domains

      Personalizar

      Como personalizar os componentes React com props


      O autor selecionou a Creative Commons para receber uma doação como parte do programa Write for DOnations.

      Introdução

      Neste tutorial você criará componentes personalizados passando props (que significa propriedades) aos seus componentes. Props são argumentos que você fornece a um elemento JSX. Elas se parecem com os props padrão do HTML, mas não são pré-definidos e podem ter diferentes tipos de dados JavaScript, incluindo números, strings, funções, matrizes e até mesmo outros componentes React. Seus componentes personalizados utilizam props para exibir dados ou utilizá-los para fazer os componentes interagirem. Os props são parte fundamental da criação de componentes adaptáveis para situações diferentes. Aprender como usá-los dará a você as ferramentas necessárias para desenvolver componentes personalizados para lidar com situações únicas.

      Após adicionar os props aos componentes, você utilizará o PropTypes para definir o tipo de dados que você espera que um componente receba. O PropTypes é um sistema de tipos simples que verifica se os dados correspondem aos tipos esperados no ambiente de execução. Ele serve como uma documentação e verificador de erros que ajudará você a manter seu aplicativo previsível à medida que ele for escalonado.

      Ao final deste tutorial, você utilizará uma variedade de props para desenvolver um aplicativo pequeno que receberá uma matriz de dados de animais. Ela mostrará informações como nome, nome científico, tamanho, dieta e outras informações.

      Nota: o primeiro passo define um projeto em branco no qual você desenvolverá o exercício do tutorial. Se você já tiver um projeto de trabalho e deseja ir diretamente ao trabalho com os props, vá para o Passo 2.

      Pré-requisitos

      Passo 1 — Criando um projeto vazio

      Neste passo, você criará um novo projeto utilizando o Create React App. Em seguida, você excluirá o projeto de exemplo e os arquivos relacionados que foram instalados durante a inicialização dele. Por fim, você criará uma estrutura de arquivos simples para organizar seus componentes.

      Para começar, crie um novo projeto. Em sua linha de comando, execute o script a seguir para instalar um novo projeto usando o create-react-app:

      • npx create-react-app prop-tutorial

      Após o projeto ser finalizado, vá para o diretório:

      Em uma nova guia ou janela do terminal, inicie o projeto usando o script start do Create React App. O navegador irá atualizar automaticamente com as alterações. Dessa forma, deixe este script em execução durante todo o tempo em que você estiver trabalhando:

      Você receberá um servidor local em execução. Se o projeto não abriu na janela de um navegador, você pode abri-lo indo para http://localhost:3000/. Se o estiver executando em um servidor remoto, o endereço será http://your_domain:3000.

      Seu navegador carregará com um aplicativo simples do React, que vem incluído como parte do Create React App:

      Projeto modelo do React

      Você desenvolverá um conjunto completamente novo de componentes personalizados. Você começará seu projeto removendo um pouco do código boilerplate para que você possa ter um projeto vazio.

      Para iniciar, abra o src/App.js em um editor de texto. Esse é o componente raiz que é injetado na página. Todos os componentes iniciarão a partir daqui. Saiba mais sobre o App.js em Como configurar um projeto React com o Create React App.

      Abra o src/App.js com o seguinte comando:

      Você verá um arquivo como este:

      prop-tutorial/src/App.js

      import React from 'react';
      import logo from './logo.svg';
      import './App.css';
      
      function App() {
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <p>
                Edit <code>src/App.js</code> and save to reload.
              </p>
              <a
                className="App-link"
                href="https://reactjs.org"
                target="_blank"
                rel="noopener noreferrer"
              >
                Learn React
              </a>
            </header>
          </div>
        );
      }
      
      export default App;
      

      Exclua a linha import logo from './logo.svg';. Em seguida, substitua tudo na instrução return para retornar um conjunto de tags vazias: <></>. Isso dará a você uma página de validação que não retorna nada. O código final ficará parecido com este:

      prop-tutorial/src/App.js

      
      import React from 'react';
      import './App.css';
      
      function App() {
        return <></>;
      }
      
      export default App;
      

      Salve e saia do editor de texto.

      Por fim, exclua o logo. Você não o usará neste seu aplicativo e é aconselhável remover arquivos não utilizados durante o trabalho. Isso evitará confusões futuras.

      Na janela do terminal, digite o seguinte comando:

      Se você olhar em seu navegador, verá uma tela vazia.

      tela vazia no chrome

      Com o projeto de exemplo do Create React App limpo, crie uma estrutura de arquivos simples. Isso ajudará você a manter os componentes isolados e independentes.

      Crie um diretório chamado components no diretório src. Ele terá todos os seus componentes personalizados.

      Cada componente terá o próprio diretório para armazenar o arquivo de componente com os estilos, imagens (se houver) e testes.

      Crie um diretório para o App:

      Mova todos os arquivos App para esse diretório. Use o curinga * para selecionar quaisquer arquivos que comecem com App., independentemente da extensão. Depois, utilize o comando mv para colocá-los no novo diretório.

      • mv src/App.* src/components/App

      Por fim atualize o caminho de importação relativo em index.js, que é o componente raiz que inicializa todo o processo.

      A instrução de importação precisa apontar para o arquivo Apps.js no diretório App. Portanto, faça a seguinte alteração destacada:

      prop-tutorial/src/index.js

      import React from 'react';
      import ReactDOM from 'react-dom';
      import './index.css';
      import App from './components/App/App';
      import * as serviceWorker from './serviceWorker';
      
      ReactDOM.render(
        <React.StrictMode>
          <App />
        </React.StrictMode>,
        document.getElementById('root')
      );
      
      // If you want your app to work offline and load faster, you can change
      // unregister() to register() below. Note this comes with some pitfalls.
      // Learn more about service workers: https://bit.ly/CRA-PWA
      serviceWorker.unregister();
      

      Salve e saia do arquivo.

      Agora que o projeto está configurado, crie o primeiro componente.

      Neste passo, você criará um componente que será modificado com base nas informações de entrada, chamadas props. Os props são argumentos que você passa para uma função ou classe. Como seus componentes são transformados em objetos semelhantes aos HTML pelo JSX, você passará os props como se fossem atributos do HTML. Diferente dos elementos HTML, você pode passar vários tipos de dados diferentes: strings, matrizes. objetos e até mesmo funções.

      Aqui, você criará um componente que exibirá as informações de animais. Esse componente terá o nome e nome científico do animal como strings, o tamanho como um número inteiro, a dieta será uma matriz de strings e as informações adicionais serão um objeto. Você passará as informações para o novo componente como props e as consumirá no componente.

      Ao final deste passo, você terá um componente que consumirá diferentes props. Você também reutilizará o componente para exibir uma matriz de dados usando um componente comum.

      Adicionando dados

      Primeiro, serão necessários dados de exemplo. Crie um arquivo no diretório src/App chamado data.

      • touch src/components/App/data.js

      Abra o novo arquivo em seu editor de texto:

      • nano src/components/App/data.js

      Em seguida, adicione uma matriz de objetos que será usada como exemplo:

      prop-tutorial/src/components/App/data.js

      export default [
        {
          name: 'Lion',
          scientificName: 'Panthero leo',
          size: 140,
          diet: ['meat'],
        },
        {
          name: 'Gorilla',
          scientificName: 'Gorilla beringei',
          size: 205,
          diet: ['plants', 'insects'],
          additional: {
            notes: 'This is the eastern gorilla. There is also a western gorilla that is a different species.'
          }
        },
        {
          name: 'Zebra',
          scientificName: 'Equus quagga',
          size: 322,
          diet: ['plants'],
          additional: {
            notes: 'There are three different species of zebra.',
            link: 'https://en.wikipedia.org/wiki/Zebra'
          }
        }
      ]
      

      A matriz de objetos contém uma variedade de dados e dará a você a oportunidade de testar uma variedade de props. Cada objeto é um animal separado com o nome dele, o nome científico, o tamanho, a dieta e um campo opcional chamado additional que contém links ou anotações. Neste código você também exportou a matriz como default.

      Salve e saia do arquivo.

      Criando componentes

      Em seguida, crie um componente de espaço reservado chamado AnimalCard. Este componente eventualmente utilizará props e exibirá os dados.

      Primeiro, crie um diretório em src/components chamado AnimalCard. Em seguida, use o comando touch para criar um arquivo chamado src/components/AnimalCard/AnimalCard.js e um arquivo CSS chamado src/components/AnimalCard/AnimalCard.css.

      • mkdir src/components/AnimalCard
      • touch src/components/AnimalCard/AnimalCard.js
      • touch src/components/AnimalCard/AnimalCard.css

      Abra o AnimalCard.js no seu editor de texto:

      • nano src/components/AnimalCard/AnimalCard.js

      Adicione um componente básico que importa o CSS e retorna uma tag <h2>.

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      import React from 'react';
      import './AnimalCard.css'
      
      export default function AnimalCard() {
        return <h2>Animal</h2>
      }
      

      Salve e saia do arquivo. Agora, é necessário que você importe os dados e os componentes em seu componente base App.

      Abra o src/components/App/App.js:

      • nano src/components/App/App.js

      Importe os dados e os componentes. Em seguida, faça um loop com os dados para retornar os componentes para cada item na matriz:

      prop-tutorial/src/components/App/App.js

      import React from 'react';
      import data from './data';
      import AnimalCard from '../AnimalCard/AnimalCard';
      import './App.css';
      
      function App() {
        return (
          <div className="wrapper">
            <h1>Animals</h1>
            {data.map(animal => (
              <AnimalCard key={animal.name}/>
            ))}
          </div>
        )
      }
      
      export default App;
      

      Salve e saia do arquivo. Aqui,utilize o método de matriz .map() para iterar os dados. Além da adição deste loop, você também terá uma div de quebra automática com uma classe que você utilizará para aplicação de estilo e uma tag <h1> para rotular seu projeto.

      Quando você salvar, o navegador será recarregado e você verá um rótulo para cada cartão.

      Projeto React no navegador sem estilo

      Em seguida, vamos aplicar o estilo para alinhar os itens. Abra o App.css:

      • nano src/components/App/App.css

      Para organizar os elementos, substitua o conteúdo pelo seguinte:

      prop-tutorial/src/components/App/App.css

      .wrapper {
          display: flex;
          flex-wrap: wrap;
          justify-content: space-between;
          padding: 20px;
      }
      
      .wrapper h1 {
          text-align: center;
          width: 100%;
      }
      

      Isso utilizará o flexbox para reorganizar os dados de modo que fiquem alinhados. O padding coloca um pouco de espaço na janela do navegador. O justify-content espalhará o espaço extra entre os elementos e o .wrapper h1 fornecerá a largura total do rótulo Animal.

      Salve e saia do arquivo. Quando fizer isso, o navegador será recarregado e você verá alguns dados espaçados.

      Projeto React no navegador com dados espaçados

      Adicionando props

      Com seus componentes configurados, adicione seu primeiro prop. Ao fazer o loop com os dados, você terá acesso a cada objeto na matriz data e a cada item que o objeto tem. Você adicionará cada um dos dados em um prop separado que você utilizará depois em seu componente AnimalCard.

      Abra App.js:

      • nano src/components/App/App.js

      Adicione um prop de name para AnimalCard.

      prop-tutorial/src/components/App/App.js

      import React from 'react';
      ...
      function App() {
        return (
          <div className="wrapper">
            <h1>Animals</h1>
            {data.map(animal => (
              <AnimalCard
                key={animal.name}
                name={animal.name}
              />
            ))}
          </div>
        )
      }
      
      export default App;
      

      Salve e saia do arquivo. O prop name se parece com um atribuito HTML padrão, mas em vez de uma string, você passará a propriedade name do objeto animal entre chaves.

      Agora que você passou um prop para o novo componente, você precisa usá-lo. Abra o AnimalCard.js:

      • nano src/components/AnimalCard/AnimalCard.js

      Todos os props que você passa para o componente são coletados em um objeto que será o primeiro argumento da função. Desestruture o objeto para extrair os props individuais:

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      
      import React from 'react';
      import './AnimalCard.css'
      
      export default function AnimalCard(props) {
        const { name } = props;
        return (
          <h2>{name}</h2>
        );
      }
      

      Observe que não é necessário desestruturar um prop para usá-lo. Esse é um método útil para lidar os com dados de exemplo neste tutorial.

      Após desestruturar o objeto, você pode usar os dados individuais. Neste caso, você utilizará o título em uma tag <h2>, colocando o valor entre chaves para que o React saiba avaliá-lo como JavaScript.

      Você também pode usar uma propriedade no objeto prop usando a notação de ponto. Por exemplo, crie um elemento <h2> assim: <h2>{props.title}</h2>. A vantagem da desestruturação é que você coleta os props não utilizados e usa o objeto operador rest.

      Salve e saia do arquivo. Quando fizer isso, o navegador será recarregado e você verá o nome específico para cada animal em vez de um espaço reservado.

      Projetos do React com nomes de animais renderizados

      A propriedade name é uma string, mas os props podem ser de qualquer tipo de dados que você poderia passar para uma função JavaScript. Para ver isto em funcionamento, adicione o resto dos dados.

      Abra o arquivo App.js:

      • nano src/components/App/App.js

      Adicione um prop para cada um dos seguintes: scientificName, size, diet e additional. Eles possuem strings, inteiros, matrizes e objetos.

      prop-tutorial/src/components/App/App.js

      import React from 'react';
      ...
      
      function App() {
        return (
          <div className="wrapper">
            <h1>Animals</h1>
            {albums.map(album => (
              <AnimalCard
                additional={animal.additional}
                diet={animal.diet}
                key={animal.name}
                name={animal.name}
                scientificName={animal.scientificName}
                size={animal.size}
              />
            ))}
          </div>
        )
      }
      
      export default App;
      

      Como está criando um objeto, você pode adicioná-los em qualquer ordem que quiser. A ordem alfabética facilita a busca em uma lista de props, principalmente em uma lista muito grande. Você também pode colocá-los na mesma linha. No entanto, separá-los um por linha facilita a leitura.

      Salve e feche o arquivo. Abra o AnimalCard.js.

      • nano src/components/AnimalCard/AnimalCard.js

      Desta vez, desestruture os props na lista de parâmetros das funções e use os dados no componente:

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      import React from 'react';
      import './AnimalCard.css'
      
      export default function AnimalCard({
        additional,
        diet,
        name,
        scientificName,
        size
      }) {
        return (
          <div>
            <h2>{name}</h2>
            <h3>{scientificName}</h3>
            <h4>{size}kg</h4>
            <div>{diet.join(', ')}.</div>
          </div>
        );
      }
      

      Após retirar os dados, adicione o scientificName e o size em tags de cabeçalho. Será necessário converter a matriz em uma string para que o React possa exibi-la na página. Faça isso com o join(', '), que criará uma lista separada por vírgula.

      Salve e feche o arquivo. Quando fizer isso, o navegador recarregará e você verá os dados estruturados.

      Projeto React com os animais com os dados completos

      Você poderia criar uma lista parecida com o objeto additional, mas, em vez disso, adicione uma função para alertar o usuário com os dados. Isso dará a você a chance de passar funções como props e utilizar os dados dentro de um componente ao chamar uma função.

      Abra App.js:

      • nano src/components/App/App.js

      Crie uma função chamada showAdditionalData, que converte o objeto em uma string e a exibirá como um alerta.

      prop-tutorial/src/components/App/App.js

      import React from 'react';
      ...
      
      function showAdditional(additional) {
        const alertInformation = Object.entries(additional)
          .map(information => `${information[0]}: ${information[1]}`)
          .join('n');
        alert(alertInformation)
      };
      
      function App() {
        return (
          <div className="wrapper">
            <h1>Animals</h1>
            {data.map(animal => (
              <AnimalCard
                additional={animal.additional}
                diet={animal.diet}
                key={animal.name}
                name={animal.name}
                scientificName={animal.scientificName}
                showAdditional={showAdditional}
                size={animal.size}
              />
            ))}
          </div>
        )
      }
      
      export default App;
      

      A função showAdditional converte o objeto para uma matriz de pares onde o primeiro item é a chave e o segundo é o valor. Em seguida, ele mapeia os dados convertendo o par de chaves para uma string. Depois, ele as junta com uma quebra de linha (n) antes de passar a string completa para a função de alerta.

      Como o JavaScript pode aceitar funções como argumentos, o React também aceita funções como props. Por este motivo, você pode passar o showAdditional para o AnimalCard como um prop chamado showAdditional.

      Salve e feche o arquivo. Abra o AnimalCard:

      • nano src/components/AnimalCard/AnimalCard.js

      Traga a função showAdditional do objeto props. Em seguida, crie um <button> com um evento onClick que chama a função com o objeto additional:

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      import React from 'react';
      import './AnimalCard.css'
      
      export default function AnimalCard({
        additional,
        diet,
        name,
        scientificName,
        showAdditional,
        size
      }) {
        return (
          <div>
            <h2>{name}</h2>
            <h3>{scientificName}</h3>
            <h4>{size}kg</h4>
            <div>{diet.join(', ')}.</div>
            <button onClick={() => showAdditional(additional)}>More Info</button>
          </div>
        );
      }
      

      Salve o arquivo. Quando fizer isso, o navegador será recarregado e você verá um botão após cada cartão. Quando você clicar no botão, receberá um alerta com os dados adicionais.

      Alerta com informações

      Se você tentar clicar em More Info para o Lion, receberá um erro. Isso acontece porque não existem dados adicionais para o leão. Você verá como corrigir isso no Passo 3.

      Finalmente, adicione um pouco de estilo ao cartão de música. Adicione um className de animal-wrapper ao div em AnimalCard:

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      import React from 'react';
      import './AnimalCard.css'
      
      export default function AnimalCard({
      ...
        return (
          <div className="animal-wrapper">
      ...
          </div>
        )
      }
      

      Salve e feche o arquivo. Abra o AnimalCard.css:

      • nano src/components/AnimalCard/AnimalCard.css

      Adicione o CSS para dar aos cartões e ao botão uma borda e um preenchimento:

      prop-tutorial/src/components/AnimalCard/AnimalCard.css

      .animal-wrapper {
          border: solid black 1px;
          margin: 10px;
          padding: 10px;
          width: 200px;
      }
      
      .animal-wrapper button {
          font-size: 1em;
          border: solid black 1px;
          padding: 10;
          background: none;
          cursor: pointer;
          margin: 10px 0;
      }
      

      Este CSS adicionará uma borda leve ao cartão e substituirá o estilo padrão do botão para um com borda e preenchimento. O cursor: pointer alterará o cursor quando você passar o mouse por cima do botão.

      Salve e feche o arquivo. Quando fizer isso, o navegador será recarregado e você verá os dados em cartões individuais.

      Projeto React com os cartões de animais com estilos aplicados

      Neste ponto, você criou dois componentes personalizados. Você passou dados para o segundo componente a partir do primeiro componente usando os props. Os props incluíram uma variedade de dados, como strings, números inteiros, matrizes, objetos e funções. Em seu segundo componente, você utilizou os props para criar um componente dinâmico usando o JSX.

      No próximo passo, você utilizará um sistema de tipos chamado de prop-types para especificar a estrutura que o componente espera ver. Este sistema criará uma previsibilidade em seu aplicativo e evitará bugs.

      Neste passo, você adicionará um sistema leve de tipos aos seus componentes com o PropTypes. O PropTypes age da mesma forma que outros sistemas de tipos, definindo explicitamente o tipo de dados que você espera receber de um certo prop. Ele também dá a você a chance de definir dados padronizados nos casos onde o prop não é muito necessário. Ao contrário da maioria dos sistemas de tipos, o PropTypes é um verificador do ambiente de execução. Desta forma, se os props não corresponderem ao tipo, o código ainda compilará, porém, ele exibirá um erro de console.

      Ao final deste passo, você adicionará a previsibilidade ao seu componente personalizado, definindo o tipo para cada prop. Isso garantirá que a próxima pessoa que trabalhar no componente tenha uma ideia clara sobre a estrutura dos dados de que o componente precisará.

      O pacote prop-types está incluído como parte da instalação do Create React App. Por este motivo, tudo que você precisa fazer é importá-lo em seu componente.

      Abra o AnimalCard.js:

      • nano src/components/AnimalCard/AnimalCard.js

      Em seguida, importe o PropTypes do prop-types:

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      import React from 'react';
      import PropTypes from 'prop-types';
      import './AnimalCard.css'
      
      export default function AnimalCard({
      ...
      }
      

      Adicione o PropTypes diretamente à função do componente. Em JavaScript, as funções são objetos. Isso significa que você pode adicionar propriedades usando a sintaxe de ponto. Adicione os seguintes PropTypes para o AnimalCard.js:

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      import React from 'react';
      import PropTypes from 'prop-types';
      import './AnimalCard.css'
      
      export default function AnimalCard({
      ...
      }
      
      AnimalCard.propTypes = {
        additional: PropTypes.shape({
          link: PropTypes.string,
          notes: PropTypes.string
        }),
        diet: PropTypes.arrayOf(PropTypes.string).isRequired,
        name: PropTypes.string.isRequired,
        scientificName: PropTypes.string.isRequired,
        showAdditional: PropTypes.func.isRequired,
        size: PropTypes.number.isRequired,
      }
      

      Salve e feche o arquivo.

      Como você pode ver, existem vários tipos diferentes de PropTypes. Esta é apenas uma pequena amostra; consulte a documentação oficial do React para ver os outros PropTypes que você pode usar.

      Vamos começar pelo prop name. Aqui, você está especificando que name deve ser do tipo string. A propriedade scientificName é a mesma coisa. O size é um número que pode incluir floats como 1.5 e inteiros como 6. O showAdditional é uma função (func).

      O diet, por outro lado, é um pouco diferente. Neste caso, você está especificando que o diet será uma array, mas você também precisa especificar o que essa matriz conterá. Neste caso, a matriz conterá apenas strings. Se quiser misturar os tipos, utilize outro prop chamado de oneOfType, que recebe uma matriz de PropTypes válidos. Você pode utilizar o oneOfType em qualquer lugar. Se quiser que o size seja tanto um número quanto uma string, modifique-o para isto:

      size: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
      

      O prop additional também é um pouco mais complexo. Neste caso, você está especificando um objeto, mas, para ficar um pouco mais claro, você está declarando o que quer que o objeto contenha. Para fazer isso, utilize o PropTypes.shape, que recebe um objeto com campos adicionais que precisarão de seus próprios PropTypes. Neste caso, o link e o notes são ambos PropTypes.string.

      No momento, todos os dados estão bem estruturados e correspondem aos props. Para ver o que acontece se o PropTypes não for correspondido, abra seus dados:

      • nano src/components/App/data.js

      Modifique o tamanho para uma string no primeiro item:

      prop-tutorial/src/components/App/data.js

      export default [
        {
          name: 'Lion',
          scientificName: 'Panthero leo',
          size: '140',
          diet: ['meat'],
        },
      ...
      ]
      

      Salve o arquivo. Quando fizer isso, o navegador recarregará e você verá um erro no console.

      Error

      index.js:1 Warning: Failed prop type: Invalid prop `size` of type `string` supplied to `AnimalCard`, expected `number`. in AnimalCard (at App.js:18) in App (at src/index.js:9) in StrictMode (at src/index.js:8)

      Navegador com erro de tipo

      Ao contrário de outros sistemas de tipos como o TypeScript, o PropTypes não dará um aviso a você no momento da compilação. Enquanto não houver erros, ele ainda compilará. Isso significa que você pode publicar um código com erros de prop acidentalmente.

      Modifique os dados de volta para o tipo correto:

      prop-tutorial/src/components/App/data.js

      export default [
        {
          name: 'Lion',
          scientificName: 'Panthero leo',
          size: 140,
          diet: ['meat'],
        },
      ...
      ]
      

      Salve e feche o arquivo.

      Abra o AnimalCard.js:

      • nano src/components/AnimalCard/AnimalCard.js

      Todo prop (com exceção do additional) possui a propriedade isRequired. Isso significa que eles são necessários. Se você não incluir um prop necessário, o código ainda compilará, mas você verá um erro do ambiente de execução no console.

      Se um prop não for necessário, você pode adicionar um valor padrão. Uma boa medida é sempre adicionar um valor padrão para evitar erros do ambiente de execução se um prop não for necessário. Por exemplo, no componente AnimalCard você está chamando uma função com os dados de additional. Se os dados não estiverem lá, a função tentará modificar um objeto que não existe e o aplicativo falhará.

      Para evitar este problema, adicione um defaultProp para o additional:

      prop-tutorial/src/components/AnimalCard/AnimalCard.js

      import React from 'react';
      import PropTypes from 'prop-types';
      import './AnimalCard.css'
      
      export default function AnimalCard({
      ...
      }
      
      AnimalCard.propTypes = {
        additional: PropTypes.shape({
          link: PropTypes.string,
          notes: PropTypes.string
        }),
      ...
      }
      
      AnimalCard.defaultProps = {
        additional: {
          notes: 'No Additional Information'
        }
      }
      

      Adicione o defaultProps à função usando a sintaxe de ponto da mesma forma que você fez com o propTypes. Em seguida, adicione um valor padrão que o componente deve usar se o prop for undefined. Neste caso, você está correspondendo o formato do additional incluindo uma mensagem de que não há informações adicionais.

      Salve e feche o arquivo. Quando fizer isso, o navegador recarregará. Após ele recarregar, clique no botão More Info para o Lion. Ele não possui um campo additional nos dados. Por este motivo, o prop está undefined. Porém, o AnimalCard será substituído no prop padrão.

      Navegador com a mensagem padrão no alerta

      Agora seus props estão bem documentados e são necessários ou possuem um padrão para garantir um código previsível. Isso ajudará que futuros desenvolvedores (incluindo você) entendam quais props de que um componente precisa. Ele facilitará a troca e a reutilização dos seus componentes, fornecendo informações completas sobre como o componente utilizará os dados que ele está recebendo.

      Conclusão

      Neste tutorial, você criou vários componentes que usam os props para exibir informações de um pai. Os props fornecem a flexibilidade que você precisa para começar a separar componentes maiores em partes menores e mais focadas. Agora que você não possui mais seus dados fortemente acoplados às informações de exibição, você pode fazer escolhas sobre como segmentar seu aplicativo.

      Os props são ferramentas importantes no desenvolvimento de aplicativos complexos. Eles dão a oportunidade de criar componentes que se adaptam aos dados que recebem. Com o PropTypes, você está criando componentes previsíveis e legíveis que darão a uma equipe a habilidade de reutilizar o trabalho uns dos outros para, desta maneira, criarem uma base de código flexível e estável. Se você quiser analisar mais tutoriais do React, dê uma olhada em nossa página sobre o React ou retorne à página da série Como Programar em React.js.



      Source link

      Personalizar los binarios de Go con etiquetas de compilación


      Introducción

      En Go, una etiqueta de compilación, o una restricción de compilación, es un identificador añadido a un fragmento de código que determina el momento en que debería incluirse el archivo en un paquete durante el proceso build. Esto le permite compilar diferentes versiones de su aplicación de Go a partir del mismo código fuente y alternar entre ellas de forma rápida y organizada. Muchos desarrolladores utilizan etiquetas de compilación para mejorar el flujo de trabajo de creación de aplicaciones compatibles entre plataformas, como programas que requieren cambios de código para tener en cuenta las variaciones entre diferentes sistemas operativos. Las etiquetas de compilación también se utilizan para pruebas de integración, lo que le permite pasar rápidamente del código integrado al código con un servicio mock o stub, y para diferentes niveles de conjuntos de funciones en una aplicación.

      Tomaremos como ejemplo el problema de los diferentes conjuntos de funciones de los clientes. Al escribir algunas aplicaciones, es posible que desee controlar las funciones que se incluirán en el binario, como en el caso de una aplicación que ofrece niveles Gratis, Pro y Empresarial. A medida que el cliente aumente su nivel de suscripción en esas aplicaciones, más funciones se desbloquearán y estarán disponibles. Para resolver este problema, podría tener proyectos separados e intentar mantenerlos sincronizados entre ellos a través de instrucciones import. Aunque este enfoque funcionaría, con el tiempo se volvería tedioso y estaría expuesto a errores. Un enfoque alternativo consistiría en usar etiquetas de compilación.

      A través de este artículo, usará etiquetas de compilación en Go para generar binarios ejecutables diferentes que ofrezcan conjuntos de funciones Gratis, Pro y Empresarial de una aplicación de ejemplo. Cada uno tendrá un conjunto diferente de funciones disponibles y la versión Gratis será la predeterminada.

      Requisitos previos

      Para seguir el ejemplo de este artículo, necesitará lo siguiente:

      Compilar la versión Gratis

      Comenzaremos creando la versión Gratis de la aplicación, ya que será la predeterminada cuando se ejecute go build sin etiquetas de compilación. Más adelante, usaremos las etiquetas de compilación para añadir otras partes a nuestro programa.

      En el directorio src, cree una carpeta con el nombre de su aplicación. En este tutorial se usará app:

      Posiciónese en esta carpeta:

      A continuación, cree en su editor de texto un nuevo archivo de texto llamado main.go:

      A continuación, definiremos la versión Gratis de la aplicación. Añada el siguiente contenido a main.go:

      main.go

      package main
      
      import "fmt"
      
      var features = []string{
        "Free Feature #1",
        "Free Feature #2",
      }
      
      func main() {
        for _, f := range features {
          fmt.Println(">", f)
        }
      }
      

      En este archivo, creamos un programa que declara un segmento llamado features, el cual contiene dos cadenas que representan las funciones de nuestra aplicación Gratis. La función main() de la aplicación utiliza un bucle for para aplicar range en el segmento features e imprimir todas las funciones disponibles en la pantalla.

      Guarde el archivo y ciérrelo. Ahora que se guardó el archivo, ya no tendremos que editarlo durante el resto del artículo. Como alternativa, utilizaremos etiquetas de compilación para cambiar las funciones de los binarios que crearemos a partir de él.

      Cree y ejecute el programa:

      Obtendrá el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2

      El programa imprimió nuestras dos funciones gratuitas y completó la versión Gratis de nuestra aplicación.

      Hasta ahora, creó una aplicación que tiene un conjunto de funciones muy básico. A continuación, compilará una alternativa para añadir más funciones a la aplicación en el tiempo de compilación.

      Añadir las funciones Pro con go build

      Hasta ahora, evitamos realizar cambios en main.go y simulamos un entorno de producción común en el cual se debe agregar código sin cambiar ni posiblemente dañar el código principal. Debido a que no podemos editar el archivo main.go, tendremos que usar otro mecanismo para inyectar más funciones en el segmento features usando etiquetas de compilación.

      Vamos a crear un nuevo archivo llamado pro.go que usará una función init() para añadir más funciones al segmento features:

      Una vez que el editor haya abierto el archivo, añada las siguientes líneas:

      pro.go

      package main
      
      func init() {
        features = append(features,
          "Pro Feature #1",
          "Pro Feature #2",
        )
      }
      

      En este código, usamos init() para ejecutar código antes de la función main() de nuestra aplicación, seguido de append() para añadir las funciones Pro al segmento features. Guarde el archivo y ciérrelo.

      Compile y ejecute la aplicación usando go build:

      Debido a que ahora hay dos archivos en nuestro directorio actual (pro.go y main.go), go build creará un binario a partir de ambos. Ejecute este binario:

      Esto le proporcionará el siguiente conjunto de funciones:

      Output

      > Free Feature #1 > Free Feature #2 > Pro Feature #1 > Pro Feature #2

      En la aplicación ahora se incluirán las funciones Pro y Gratis. Sin embargo, esto no es conveniente. Debido a que no existe una distinción entre las versiones, la Gratis ahora incluye las funciones que, según se supone, solo deben estar disponibles en la versión Pro. Para solucionar esto, podría incluir más código para administrar los diferentes niveles de la aplicación o podría usar etiquetas de compilación para indicar a la cadena de herramientas de Go los archivos .go que desea crear e ignorar. Añadiremos etiquetas de compilación en el siguiente paso.

      Agregar etiquetas de compilación

      Ahora puede usar las etiquetas de compilación para distinguir la versión Pro y la Gratis de su aplicación.

      Comenzaremos examinando el aspecto que tiene una etiqueta de compilación:

      // +build tag_name
      

      Al disponer esta línea de código como la primera de su paquete y sustituir tag_name por el nombre de su etiqueta de compilación, etiquetará este paquete como un código que puede incluirse selectivamente en el binario final. Veremos esto en acción añadiendo una etiqueta de compilación al archivo pro.go para indicar al comando go build que lo ignore a menos que se especifique la etiqueta. Abra el archivo en su editor de texto:

      A continuación, añada la siguiente línea resaltada:

      pro.go

      // +build pro
      
      package main
      
      func init() {
        features = append(features,
          "Pro Feature #1",
          "Pro Feature #2",
        )
      }
      

      En la parte superior del archivo pro.go, añadimos // +build pro seguido de una nueva línea en blanco. Esta nueva línea final es necesaria; de lo contrario, Go interpreta esto como un comentario. En la parte superior de un archivo .go también declaraciones de etiquetas de compilación. No puede haber nada, ni siquiera comentarios, sobre las etiquetas de compilación.

      La declaración +build indica al comando go build que esto no es un comentario, sino una etiqueta de compilación. La segunda parte es la etiqueta pro. Al añadirse esta etiqueta a la parte superior del archivo pro.go, el comando go build ahora incluirá únicamente el archivo pro.go cuando la etiqueta pro esté presente.

      Compile y ejecute la aplicación de nuevo:

      Obtendrá el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2

      Debido a que requiere que haya una etiqueta pro presente, el archivo pro.go se ignora y la aplicación realiza la compilación sin él.

      Cuando se ejecuta el comando go build, podemos usar el indicador -tags para incluir condicionalmente código en la fuente compilada añadiendo la etiqueta como argumento. Haremos esto para la etiqueta pro:

      Esto dará el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2 > Pro Feature #1 > Pro Feature #2

      Ahora, solo obtendremos las funciones adicionales cuando compilemos la aplicación usando la etiqueta de compilación pro.

      Esto está bien si solo hay dos versiones, pero la situación se complica cuando añade más etiquetas. Para añadir la versión Empresarial de nuestra aplicación en el siguiente paso, utilizaremos varias etiquetas de compilación unidas con lógica booleana.

      Lógica de booleanos para etiquetas de compilación

      Cuando hay varias etiquetas de compilación en un paquete de Go, las etiquetas interactúan entre ellas usando lógica de booleanos. Para demostrar esto, añadiremos el nivel Empresarial de nuestra aplicación usando las etiquetas pro y enterprise.

      Para crear un binario de Empresarial, debemos incluir las funciones predeterminadas, las funciones del nivel Pro y un nuevo conjunto de funciones para Empresarial. Primero, abra un editor y cree un nuevo archivo, enterprise.go, que añadirá las nuevas funciones Empresarial:

      El contenido de enterprise.go tendrá un aspecto casi idéntico a pro.go, pero contendrá nuevas funciones. Añada las líneas siguientes al archivo:

      enterprise.go

      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Guarde el archivo y ciérrelo.

      Actualmente, el archivo enterprise.go no tiene ninguna etiqueta de compilación y, tal como aprendió cuando añadió pro.go, esto significa que estas funciones se añadirán a la versión Gratis cuando se ejecuta go.build. Para pro.go, agregó // +build pro y una nueva línea en la parte superior del archivo a fin de indicar a go build que solo debería incluirse cuando se utilice -tags pro. En esta situación, solo necesitó una etiqueta de compilación para lograr el objetivo. Cuando se añaden las nuevas funciones Empresarial, sin embargo, primero debe también disponer de las funciones Pro.

      Añadiremos primero compatibilidad con la etiqueta de compilación pro a enterprise.go. Abra el archivo con su editor de texto:

      A continuación, añada la etiqueta de compilación antes de la declaración package main y asegúrese de incluir una línea nueva después de la etiqueta de compilación:

      enterprise.go

      // +build pro
      
      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Guarde el archivo y ciérrelo.

      Compile y ejecute la aplicación sin etiquetas:

      Obtendrá el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2

      Las funciones Empresariales ya no se muestran en la versión Gratis. Ahora, añadiremos la etiqueta de compilación pro, y compilaremos y ejecutaremos la aplicación de nuevo:

      Obtendrá el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2 > Pro Feature #1 > Pro Feature #2

      Esto no es exactamente lo que necesitamos: las funciones Empresarial ahora se muestran cuando intentamos compilar la versión Pro. Para resolver esto, debemos usar otra etiqueta de compilación. A diferencia de lo que sucede con la etiqueta pro, sin embargo, debemos asegurarnos de que las funciones pro y enterprise estén disponibles.

      El sistema de compilación de Go tiene en cuenta esta situación al permitir el uso de lógica de booleanos básica en el sistema de etiquetas de compilación.

      Abriremos de nuevo enterprise.go:

      Añada otra etiqueta de compilación, enterprise, en la misma línea de la etiqueta pro:

      enterprise.go

      // +build pro enterprise
      
      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Guarde y cierre el archivo.

      Ahora, compilaremos y ejecutaremos la aplicación con la nueva etiqueta de compilación enterprise.

      • go build -tags enterprise
      • ./app

      Esto dará el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2

      Con esto, habremos perdido las funciones Pro. Esto se debe a que cuando disponemos varias etiquetas de compilación en la misma línea en un archivo .go, go build interpreta que usan la lógica OR. Con la adición de la línea // +build pro enterprise, el archivo enterprise.go se compilará si cualquiera de las etiquetas de compilación pro o enterprise están presentes. Debemos configurar las etiquetas de compilación correctamente para requerir ambas y usar, por el contrario, la lógica AND.

      Si en vez de disponer ambas etiquetas en la misma línea las situamos en líneas separadas, go build interpretará esas etiquetas usando la lógica AND.

      Abra enterprise.go de nuevo. Separaremos las etiquetas de compilación en varias líneas.

      enterprise.go

      // +build pro
      // +build enterprise
      
      package main
      
      func init() {
        features = append(features,
          "Enterprise Feature #1",
          "Enterprise Feature #2",
        )
      }
      

      Ahora, compile y ejecute la aplicación con la nueva etiqueta de compilación enterprise.

      • go build -tags enterprise
      • ./app

      Obtendrá el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2

      Aun no terminamos: debido a que una instrucción AND requiere que ambos elementos se consideren como true, debemos usar las etiquetas de compilación pro y enterprise.

      Haremos un nuevo intento:

      • go build -tags "enterprise pro"
      • ./app

      Obtendrá el siguiente resultado:

      Output

      > Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2 > Pro Feature #1 > Pro Feature #2

      Ahora, nuestra aplicación puede crearse a partir del mismo árbol de origen de varias formas desbloqueando las funciones de la aplicación de manera correspondiente.

      En este ejemplo, usanos una nueva etiqueta // +build para representar la lógica AND, pero existen formas alternativas de representar la lógica de booleanos con etiquetas de compilación. La siguiente tabla contiene algunos ejemplos de otros formatos sintácticos para etiquetas de compilación, junto con su equivalente booleano:

      Sintaxis de la etiqueta de compilación Ejemplo de etiqueta de compilación Instrucción booleana
      Elementos separados por espacios // +build pro enterprise pro OR enterprise
      Elementos separados por comas // +build pro enterprise pro AND enterprise
      Elementos con signo de exclamación // + build ! pro NOT pro

      Conclusión

      A lo largo de este tutorial, utilizó etiquetas de compilación para controlar la parte de su código que se compilaría en el binario. Primero, declaró las etiquetas de compilación y las utilizó con go build, y luego combinó varias etiquetas con lógica de booleanos. Luego creó un programa que representó los tres conjuntos diferentes de funciones de una versión Gratis, Pro y Empresarial, y mostró el potente nivel de control que las etiquetas de compilación pueden proporcionarle en sus proyectos.

      Si desea obtener más información sobre las etiquetas de compilación, consulte la documentación de Golang relacionada con este tema o siga explorando nuestra serie Cómo crear código en Go.



      Source link