Na parte de hoje da tradução do tutorial do React, falaremos sobre propriedades de componentes. Este é um dos conceitos mais importantes refletidos nesta biblioteca.

→
Parte 1: visão geral do curso, razões para a popularidade do React, ReactDOM e JSX→
Parte 2: componentes funcionais→
Parte 3: arquivos de componentes, estrutura do projeto→
Parte 4: componentes pai e filho→
Parte 5: início do trabalho em um aplicativo TODO, noções básicas de estilo→
Parte 6: sobre alguns recursos do curso, JSX e JavaScript→
Parte 7: estilos embutidos→
Parte 8: trabalho contínuo na aplicação TODO, familiaridade com as propriedades dos componentes→
Parte 9: propriedades do componente→
Parte 10: Workshop sobre como trabalhar com propriedades e estilo de componentes→
Parte 11: geração dinâmica de marcação e método de matrizes de mapas→
Parte 12: workshop, terceira etapa do trabalho em uma aplicação TODO→
Parte 13: componentes baseados em classe→
Parte 14: workshop sobre componentes baseados em classe, status dos componentes→
Parte 15: oficinas de saúde componentes→
Parte 16: a quarta etapa do trabalho em um aplicativo TODO, manipulação de eventos→
Parte 17: quinta etapa do trabalho em um aplicativo TODO, modificando o estado dos componentes→
Parte 18: a sexta etapa do trabalho em um aplicativo TODO→
Parte 19: métodos do ciclo de vida dos componentesParte 20: a primeira lição sobre renderização condicional→
Parte 21: segunda lição e workshop sobre renderização condicional→
Parte 22: sétima etapa do trabalho em um aplicativo TODO, baixando dados de fontes externas→
Parte 23: primeira lição sobre como trabalhar com formulários→
Parte 24: Segunda lição sobre formulários→
Parte 25: Workshop sobre como trabalhar com formulários→
Parte 26: arquitetura do aplicativo, padrão Container / Component→
Parte 27: projeto do cursoLição 19. Propriedades do componente no React
→
OriginalCrie um novo projeto usando
create-react-app
e altere o código de vários arquivos padrão da pasta
src
.
Aqui está o código para o arquivo
index.js
:
import React from "react" import ReactDOM from "react-dom" import "./index.css" import App from "./App" ReactDOM.render(<App />, document.getElementById("root"))
Aqui estão os estilos descritos no arquivo
index.css
:
body { margin: 0; } .contacts { display: flex; flex-wrap: wrap; } .contact-card { flex-basis: 250px; margin: 20px; } .contact-card > img { width: 100%; height: auto; } .contact-card > h3 { text-align: center; } .contact-card > p { font-size: 12px; }
Aqui está o código encontrado no arquivo
App.js
:
import React from "react" function App() { return ( <div className="contacts"> <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/200"/> <h3><font color="#3AC1EF">▍Fluffykins</font></h3> <p>Phone: (212) 555-2345</p> <p>Email: fluff@me.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/300"/> <h3><font color="#3AC1EF">▍Destroyer</font></h3> <p>Phone: (212) 555-3456</p> <p>Email: ofworlds@yahoo.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/200/100"/> <h3><font color="#3AC1EF">▍Felix</font></h3> <p>Phone: (212) 555-4567</p> <p>Email: thecat@hotmail.com</p> </div> </div> ) } export default App
Aqui está a aparência deste aplicativo em um navegador.
Página do aplicativo no navegadorApós analisar o código e a aparência do aplicativo, podemos concluir que seria bom usar componentes especiais para exibir cartões com informações sobre animais. Agora esses elementos são formados por meio do componente
App
. Considerando o que falamos nas aulas anteriores, você pode ir além - pense em um componente universal que pode ser personalizado passando atributos ou propriedades para ele.
Em nosso aplicativo, existem cartões com imagens de gatos, seus nomes e informações de contato de seus proprietários (ou talvez deles mesmos) - um telefone e um endereço de e-mail. Para criar um componente que mais tarde se tornará a base para todos esses cartões, você pode usar um dos fragmentos de marcação retornados pelo componente
App
. Por exemplo - isto:
<div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div>
O aplicativo retorna quatro desses blocos, cada um dos quais poderia ser usado para criar um componente independente, mas essa abordagem não nos convém. Portanto, criaremos um componente que se tornará a base de todos os cartões exibidos pelo aplicativo. Para fazer isso, crie um novo arquivo de componente na pasta
src
-
ContactCard.js
e insira um código que retorne o primeiro elemento
<div>
retornado pelo componente
App
, cujo código é fornecido acima. Aqui está o código para o componente
ContactCard
:
import React from "react" function ContactCard() { return ( <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> ) } export default ContactCard
É claro que, se você criar várias instâncias desse componente, todas elas conterão os mesmos dados, pois esses dados são codificados no código do componente. E gostaríamos de, ao criar instâncias diferentes desse componente, seria possível personalizar os dados exibidos por ele. O ponto é que o componente pode receber certas propriedades, que ele pode usar.
Trabalhamos com componentes funcionais, que são funções JS comuns, nas quais, graças à biblioteca React, construções especiais podem ser usadas. Como você sabe, as funções podem receber argumentos, embora possam ser usadas sem argumentos. Um
ContactCard
nosso componente
ContactCard
, na forma em que ele existe agora, pode ser uma função tão simples que, sem aceitar nada, simplesmente retorna a soma de dois números:
function addNumbers() { return 1 + 1 }
Ele pode ser usado para descobrir a soma dos números 1 e 1, mas, por exemplo, para adicionar 1 e 2, usando funções que não aceitam nenhuma entrada, teríamos que escrever uma nova função. É bastante óbvio que essa abordagem levará a enormes inconvenientes se você precisar adicionar números diferentes; portanto, em tal situação, seria sensato criar uma função universal para adicionar números que usem dois números e retornem sua soma:
function addNumbers(a, b) { return a + b }
O retorno de tal função dependerá de quais argumentos foram passados para ela quando chamados. Ao criar componentes React, podemos seguir exatamente da mesma maneira.
Importamos o componente
App.js
ContactCard
e retornamos quatro de suas instâncias, sem excluir o código que forma os cartões na página do aplicativo por enquanto:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard /> <ContactCard /> <ContactCard /> <ContactCard /> <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/200"/> <h3><font color="#3AC1EF">▍Fluffykins</font></h3> <p>Phone: (212) 555-2345</p> <p>Email: fluff@me.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/300"/> <h3><font color="#3AC1EF">▍Destroyer</font></h3> <p>Phone: (212) 555-3456</p> <p>Email: ofworlds@yahoo.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/200/100"/> <h3><font color="#3AC1EF">▍Felix</font></h3> <p>Phone: (212) 555-4567</p> <p>Email: thecat@hotmail.com</p> </div> </div> ) } export default App
Agora vamos trabalhar no código usado para instanciar o componente
ContactCard
. Ao criar elementos HTML regulares, podemos personalizar seus atributos que afetam seu comportamento e aparência. Os nomes desses atributos são codificados pelo padrão. No caso de componentes, você pode usar exatamente a mesma abordagem, com a única diferença de que nós mesmos inventamos os nomes dos atributos e decidimos por nós mesmos como eles serão usados no código do componente.
Cada um dos cartões contém quatro informações, que, de cartão para cartão, podem ser alteradas. Esta é uma imagem de um gato e seu nome, além de um telefone e endereço de email. Deixe o nome do gato contido na propriedade
name
, o endereço da imagem na propriedade
imgURL
, o telefone na propriedade
phone
e o endereço de email na propriedade
email
.
Definimos essas propriedades para instâncias dos componentes do
ContactCard
e, ao transferir dados do código que já está no
App
, excluiremos os fragmentos correspondentes. Como resultado, o código do componente
App
ficará assim:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard name="Mr. Whiskerson" imgUrl="http://placekitten.com/300/200" phone="(212) 555-1234" email="mr.whiskaz@catnap.meow" /> <ContactCard name="Fluffykins" imgUrl="http://placekitten.com/400/200" phone="(212) 555-2345" email="fluff@me.com" /> <ContactCard name="Destroyer" imgUrl="http://placekitten.com/400/300" phone="(212) 555-3456" email="ofworlds@yahoo.com" /> <ContactCard name="Felix" imgUrl="http://placekitten.com/200/100" phone="(212) 555-4567" email="thecat@hotmail.com" /> </div> ) } export default App
É verdade que a mera transferência de propriedades para um componente não é suficiente para serem usadas nele. A página, que será formada pelo componente
App
acima, conterá quatro cartões idênticos, cujos dados são definidos no código do componente
ContactCard
, que ainda não sabe o que fazer com as propriedades transferidas para ele.
Os dados do cartão são codificados no código; o componente não pode funcionar com as propriedades passadas para elePortanto, agora é hora de falar sobre como o componente
ContactCard
pode funcionar com as propriedades que são passadas para ele quando é instanciado.
Procedemos para resolver esse problema indicando, ao declarar a função
ContactCard
, que ele aceita o parâmetro
props
. Nesse caso, o código do componente terá a seguinte aparência:
import React from "react" function ContactCard(props) { return ( <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> ) } export default ContactCard
De fato, esse parâmetro pode ser chamado como você quiser, mas no React é habitual chamá-lo de
props
, e as propriedades sobre as quais estamos falando aqui são frequentemente chamadas simplesmente de “adereços”.
O parâmetro
props
é um objeto. As propriedades deste objeto são as propriedades que são passadas para o componente quando ele é instanciado. Ou seja, por exemplo, em nosso objeto
props
haverá uma propriedade
props.name
contendo o nome do gato passado para o componente quando ele foi instanciado. Além disso, ele terá propriedades
props.imgUrl
,
props.phone
,
props.email
. Para verificar isso, adicione o comando
console.log(props)
no início da função
ContactCard
.
import React from "react" function ContactCard(props) { console.log(props) return ( <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> ) } export default ContactCard
Isso trará o objeto de
props
recebido pelo componente para o console.
Objeto de objetos do consoleAqui você pode ver a saída de quatro objetos do
ContactCard.js
. Existem muitos deles porque criamos quatro instâncias do componente
ContactCard
.
Tudo isso nos dá a oportunidade de usar no código do componente, em vez de valores codificados, o que foi passado ao criar sua instância, disponível na forma de
props
objeto
props
.
E se tentarmos usar a propriedade
props.imgUrl
esta:
<img align="center" src=props.imgUrl/>
À primeira vista, essa construção pode funcionar, mas lembre-se de que aqui precisamos usar uma entidade do JavaScript no código JSX. Falamos sobre como isso é feito em uma das classes anteriores. Ou seja, no nosso caso, a propriedade do objeto deve estar entre chaves:
<img align="center" src={props.imgUrl}/>
Processamos os outros elementos retornados pelo componente da mesma maneira, após o qual seu código assumirá o seguinte formato:
import React from "react" function ContactCard(props) { return ( <div className="contact-card"> <img align="center" src={props.imgUrl}/> <h3><font color="#3AC1EF">▍{props.name}</font></h3> <p>Phone: {props.phone}</p> <p>Email: {props.email}</p> </div> ) } export default ContactCard
Observe que nos campos para exibir o telefone e o endereço de e-mail, deixamos os textos
Phone:
e
Email:
com espaços a seguir, pois esses textos são usados em todos os componentes. Se você agora olhar para a página do aplicativo, notará que ela contém quatro cartões diferentes.
Página formada usando um componente universalNosso componente aceita apenas quatro propriedades. E se um componente precisar passar, por exemplo, 50 propriedades? Talvez passar cada propriedade como uma linha separada, como é feito no componente
App
, seja inconveniente. Nesses casos, você pode usar outra maneira de transferir propriedades para componentes. Consiste no fato de que, ao criar uma instância de um componente, não é transferida uma lista de propriedades, mas um objeto com propriedades. Veja como isso pode parecer no exemplo do primeiro componente:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard contact={{ name: "Mr. Whiskerson", imgUrl: "http://placekitten.com/300/200", phone: "(212) 555-1234", email: "mr.whiskaz@catnap.meow" }} /> <ContactCard name="Fluffykins" imgUrl="http://placekitten.com/400/200" phone="(212) 555-2345" email="fluff@me.com" /> <ContactCard name="Destroyer" imgUrl="http://placekitten.com/400/300" phone="(212) 555-3456" email="ofworlds@yahoo.com" /> <ContactCard name="Felix" imgUrl="http://placekitten.com/200/100" phone="(212) 555-4567" email="thecat@hotmail.com" /> </div> ) } export default App
Isso não quer dizer que essa abordagem reduziu significativamente a quantidade de código usada para descrever a instância do componente. O fato é que as propriedades passadas para o componente ainda são codificadas no código, embora apenas passemos um componente para o componente. As vantagens dessa abordagem podem ser sentidas em situações em que os dados para o componente são obtidos de algumas fontes externas. Por exemplo, de um arquivo JSON.
Durante a modificação do código do componente
App
usado para criar a primeira instância do componente
ContactCard
, a operação correta do aplicativo foi interrompida. É assim que a página dele ficará agora.
Mau funcionamento do aplicativoComo isso pode ser corrigido? Para entender isso, será útil analisar o que está acontecendo usando o
console.log(props)
.
Análise do objeto propsComo você pode ver, o objeto
props
do primeiro componente é diferente do mesmo objeto do segundo e do próximo componente.
No componente
ContactCard
usamos o objeto
props
base na suposição de que ele possui o
name
imgUrl
e outras propriedades. Aqui, o primeiro componente recebe apenas uma propriedade -
contact
. Isso leva ao fato de que o objeto
props
possui apenas uma propriedade -
contact
, que é o objeto, e o código do componente não fornece trabalho com essa estrutura.
Converter nosso componente no modelo de uso de apenas uma propriedade de um objeto de
contact
contendo outras propriedades é bastante simples. Para fazer isso, por exemplo, para acessar a propriedade
name
, basta usar uma construção do formulário
props.contact.name
no código do componente. Projetos semelhantes nos permitem trabalhar adequadamente com outras propriedades de que precisamos.
Vamos reciclar o código do componente, levando em consideração a transferência para ele de um único
contact
propriedade-objeto que contém outras propriedades:
import React from "react" function ContactCard(props) { console.log(props) return ( <div className="contact-card"> <img align="center" src={props.contact.imgUrl}/> <h3><font color="#3AC1EF">▍{props.contact.name}</font></h3> <p>Phone: {props.contact.phone}</p> <p>Email: {props.contact.email}</p> </div> ) } export default ContactCard
O primeiro componente agora deve ser exibido normalmente, mas não veremos isso nesta fase do projeto, pois o sistema nos informará sobre muitos erros relacionados ao fato de que várias instâncias do componente
ContactCard
criadas no componente
App
não recebem a propriedade objeto de
contact
. Ao executar o código, essa propriedade será
undefined
. Como resultado, é feita uma tentativa de se referir a uma determinada propriedade de valor
undefined
, o que leva a um erro. Corrigiremos isso processando o código do componente
App
responsável pela formação dos componentes
ContactCard
:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard contact={{ name: "Mr. Whiskerson", imgUrl: "http://placekitten.com/300/200", phone: "(212) 555-1234", email: "mr.whiskaz@catnap.meow" }} /> <ContactCard contact={{ name: "Fluffykins", imgUrl: "http://placekitten.com/400/200", phone: "(212) 555-2345", email: "fluff@me.com" }} /> <ContactCard contact={{ name: "Destroyer", imgUrl: "http://placekitten.com/400/300", phone: "(212) 555-3456", email: "ofworlds@yahoo.com" }} /> <ContactCard contact={{ name: "Felix", imgUrl: "http://placekitten.com/200/100", phone: "(212) 555-4567", email: "thecat@hotmail.com" }} /> </div> ) } export default App
Agora a página do aplicativo terá a mesma aparência de antes.
Como sempre, é recomendável que você experimente os conceitos que aprendeu hoje para entendê-los melhor. Por exemplo, você pode trabalhar com o código, adicionar novas propriedades que são passadas para o componente e tentar usá-las no componente.
Sumário
Hoje, introduzimos o conceito de propriedades que podem ser passadas para os componentes React, a fim de controlar seu comportamento e aparência. Essas propriedades se assemelham aos atributos dos elementos HTML, mas, usando as propriedades dos componentes, o programador decide independentemente qual o significado que eles têm e o que exatamente fazer com eles no componente. Da próxima vez, você terá uma lição prática sobre como trabalhar com propriedades e estilo de componentes.
Caros leitores! Como você experimentou o código do exemplo de hoje para entender melhor as propriedades dos componentes do React?