Na parte de hoje da tradução do tutorial do React, falaremos sobre o uso do método padrão da matriz map () para organizar a formação dinâmica da marcação JSX, descrevendo conjuntos de elementos do mesmo tipo.

→
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 21. Geração dinâmica de marcação e método de matrizes de mapa
→
OriginalContinuaremos o trabalho a partir do momento em que paramos de concluir a tarefa prática anterior. Lembre-se de que o código do arquivo
App.js
parecia com o seguinte:
import React from "react" import Joke from "./Joke" function App() { return ( <div> <Joke punchLine="It's hard to explain puns to kleptomaniacs because they always take things literally." /> <Joke question="What's the best thing about Switzerland?" punchLine="I don't know, but the flag is a big plus!" /> <Joke question="Did you hear about the mathematician who's afraid of negative numbers?" punchLine="He'll stop at nothing to avoid them!" /> <Joke question="Hear about the new restaurant called Karma?" punchLine="There's no menu: You get what you deserve." /> <Joke question="Did you hear about the actor who fell through the floorboards?" punchLine="He was just going through a stage." /> <Joke question="Did you hear about the claustrophobic astronaut?" punchLine="He just needed a little space." /> </div> ) } export default App
O componente
App
exibe um conjunto de componentes
Joke
. É assim que a página do aplicativo fica nessa fase do trabalho.
Página de aplicaçãoAs propriedades
question
e
punchLine
são passadas para alguns desses componentes e apenas
punchLine
para
punchLine
. Os valores para essas propriedades agora estão configurados no código de instanciação do componente
Joke
em texto sem formatação. Na realidade, a maior parte dos dados exibidos nas páginas dos aplicativos React entra no aplicativo como resultado de solicitações HTTP para determinadas APIs. Essas APIs são suportadas por meio de servidores que recebem informações dos bancos de dados, formatam no formato JSON e enviam esse código para partes de aplicativos clientes. Ainda não atingimos esse nível para atender a solicitações de API; agora, como fonte de dados, usaremos um arquivo com dados que podem ser obtidos analisando a resposta JSON do servidor. Ou seja, será um arquivo
jokesData.js
com o seguinte conteúdo:
const jokesData = [ { id: 1, punchLine: "It's hard to explain puns to kleptomaniacs because they always take things literally." }, { id: 2, question: "What's the best thing about Switzerland?", punchLine: "I don't know, but the flag is a big plus!" }, { id: 3, question: "Did you hear about the mathematician who's afraid of negative numbers?", punchLine: "He'll stop at nothing to avoid them!" }, { id: 4, question: "Hear about the new restaurant called Karma?", punchLine: "There's no menu: You get what you deserve." }, { id: 5, question: "Did you hear about the actor who fell through the floorboards?", punchLine: "He was just going through a stage." }, { id: 6, question: "Did you hear about the claustrophobic astronaut?", punchLine: "He just needed a little space." } ] export default jokesData
Este arquivo estará localizado no diretório
src
do nosso projeto.
Novo arquivo na pasta srcDe fato, ele contém uma matriz de objetos. Uma matriz semelhante pode ser obtida analisando os dados JSON recebidos de uma determinada API. Exportamos deste arquivo uma matriz de
jokesData
. Se necessário, podemos importar esse arquivo para o componente em que é necessário e imaginar que estamos trabalhando não com os dados extraídos do arquivo, mas com o que nos devolveu alguma API.
Agora que temos uma matriz de dados de origem, vamos pensar em como transformar esses dados em um conjunto de instâncias dos componentes do React.
Muitos desenvolvedores dizem que, graças ao domínio do React, eles aprenderam mais sobre JavaScript. A razão para isso é que ações semelhantes à que falaremos em outras estruturas, como Angular e Vue, são executadas usando alguns meios especiais. E no React, isso é feito usando JavaScript regular.
Em particular, planejamos usar alguns métodos padrão de matrizes, que são funções de ordem superior. Esses métodos podem, como argumentos, aceitar funções descritas por programadores. São essas funções que determinam o que uma chamada para um ou outro método padrão fará com os elementos da matriz.
Suponha que tenhamos uma matriz numérica:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Podemos processar essa matriz usando o método padrão da matriz
map()
, passando-lhe uma determinada função que define a ordem de conversão dos elementos dessa matriz. No nosso caso, essa função passará, um de cada vez, os números dessa matriz. Uma função pode fazer qualquer coisa com eles, após o que o que retornará irá para uma nova matriz, para um elemento cujo índice corresponda ao índice do elemento que está sendo processado. Se precisarmos formar uma nova matriz, cujos elementos são elementos da matriz original, multiplicados por 2, será algo assim:
const doubled = nums.map(function(num) { return num * 2 })
Verifique o funcionamento deste código:
console.log(doubled)
Se você não conheceu os
métodos de matriz antes - como
map()
,
filter()
,
reduce()
e outros - é recomendável lidar com eles.
Aqui, usaremos o método
map()
para gerar automaticamente uma lista de instâncias de componentes.
Vamos voltar ao nosso exemplo. Importe o arquivo
App.js
para o arquivo
App.js
É feito assim:
import jokesData from "./jokesData"
Depois disso, no código do programa, podemos trabalhar com o array
jokesData
. Ou seja, vamos usar o método
map()
. Aqui está como será o "espaço em branco" desse método.
jokesData.map(joke => { })
Observe que aqui estamos passando a função de seta para o método
map()
. No nosso caso, isso nos permite tornar o código mais compacto. Como a função usa apenas um parâmetro (
joke
), quando declarada, podemos ficar sem parênteses.
A partir da função passada para o método
map()
, queremos retornar uma nova instância do componente
Joke
, para a qual as propriedades
question
e
punchLine
do elemento da matriz
punchLine
vieram para ele são
punchLine
para ele. Aqui está o que pode parecer:
jokesData.map(joke => { return ( <Joke question={joke.question} punchLine={joke.punchLine} /> ) })
Este código pode ser reduzido se dois fatos forem levados em consideração. Primeiro,
return
retorna apenas um elemento, para que você possa colocá-lo imediatamente após o
return
, eliminando a necessidade de parênteses. Em segundo lugar, a função de seta contém apenas a operação de retornar um determinado valor; portanto, ao declarar essa função, você pode fazer sem a palavra-chave
return
e sem chaves. Além disso, lembramos que, como resultado do método
map()
, uma nova matriz é formada. Essa matriz precisa ser salva em algum lugar. Todas essas considerações nos levam ao seguinte:
const jokeComponents = jokesData.map(joke => <Joke question={joke.question} punchLine={joke.punchLine} />)
A constante
jokeComponents
agora conterá uma matriz, cada elemento da qual é uma descrição de uma instância do componente
Joke
com as propriedades
question
e
punchLine
passadas para ele.
O que fazemos agora com essa matriz de componentes? O React torna muito conveniente trabalhar com essas matrizes. Ou seja, estamos falando sobre o fato de que essa matriz pode ser usada no código JSX. Aqui está como será o código do arquivo do
App
:
import React from "react" import Joke from "./Joke" import jokesData from "./jokesData" function App() { const jokeComponents = jokesData.map(joke => <Joke question={joke.question} punchLine={joke.punchLine} />) return ( <div> {jokeComponents} </div> ) } export default App
Depois disso, a página do aplicativo terá a mesma aparência de antes, no entanto, você verá o seguinte aviso no console do navegador:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `App`. See https:
Seu significado se resume ao fato de que os elementos da matriz devem ter uma propriedade-
key
exclusiva. Não entraremos em detalhes sobre o motivo pelo qual o React espera a propriedade de
key
exclusiva dos componentes duplicados. Basta que levemos em consideração o fato de que, ao executar a criação em massa de instâncias de componentes, como a que acabamos de executar usando o método
map()
, as instâncias precisam passar a propriedade
key
. Além disso, essa propriedade pode ser passada para a própria instância do componente e, por exemplo, para a
<div>
, na qual o código do componente está incluído. Isso não desempenha um papel especial.
Portanto, é necessário atribuir à propriedade
key
algum valor exclusivo. Como regra, nos objetos de dados recebidos da API, existem alguns identificadores (propriedades como
id
). O principal para nós é a sua singularidade. Por exemplo, poderíamos definir a propriedade
key
como
joke.question
- todos os textos nessas propriedades são exclusivos em nosso aplicativo. Mas faremos o contrário. Lembre-se de como são os objetos com dados da matriz que exportamos do arquivo
jokesData.js
. Aqui está um fragmento:
const jokesData = [ { id: 1, punchLine: "It's hard to explain puns to kleptomaniacs because they always take things literally." }, { id: 2, question: "What's the best thing about Switzerland?", punchLine: "I don't know, but the flag is a big plus!" }, ... ]
Cada objeto possui uma propriedade
id
, cuja singularidade mantemos independentemente. São os valores dessas propriedades que podem ser usados como valores para a propriedade da
key
.
Agora, o código para criar uma matriz de instâncias de componentes no
App.js
terá o seguinte formato:
const jokeComponents = jokesData.map(joke => <Joke key={joke.id} question={joke.question} punchLine={joke.punchLine} />)
Se você fizer essa alteração no código, dê uma olhada na página do aplicativo no navegador e verifique o conteúdo do console. Acontece que a notificação sobre a propriedade da
key
desapareceu.
Depois de todas as transformações que submetemos o projeto, a aparência da página do aplicativo não mudou. No entanto, o código do componente
App
tornou-se muito mais curto e claro, e os dados para formar a lista de componentes agora são extraídos de algo que se assemelha fortemente a uma fonte de dados externa. É dessa maneira que aplicativos reais funcionam.
Além disso, deve-se notar que o núcleo da modificação do código acima foi o uso do método padrão da matriz
map()
. Usamos a técnica de criar uma lista de instâncias do componente
Joke
no componente
App
, mas nada nos impede, se necessário, de usar a mesma abordagem no componente
Joke
, que pode, com base nos dados transferidos para ele, criar nossa própria lista de instâncias de um determinado componente.
Ao mesmo tempo, como já dissemos, entre os métodos padrão de matrizes, você pode encontrar outras ferramentas interessantes. Por exemplo, o método
sort()
pode ser usado para classificar elementos da matriz por algum atributo. O método
filter()
pode ser usado para selecionar apenas os elementos da matriz que atendem a determinados critérios. Tudo isso se aplica ao trabalho com matrizes que contêm instâncias de componentes.
Se você quiser, pode experimentar com esses métodos. Digamos que tente usar o método
filter()
e remova da saída gerada pelo componente
App
aquelas instâncias do componente
Joke
cuja propriedade de
question
não exceda o comprimento especificado. Ou certifique-se de que apenas os componentes para os quais a propriedade da
question
e a propriedade
punchLine
estejam
punchLine
sejam
punchLine
.
Sumário
Hoje falamos sobre o uso do método de matriz padrão
map()
para compilar listas de componentes e também discutimos as possibilidades que outros métodos de matriz padrão nos oferecem. Da próxima vez, você terá uma lição prática sobre o material estudado hoje.
Caros leitores! Como você resolveria o problema de exibir pelo componente App apenas as instâncias do componente Joke cuja propriedade de pergunta excede o comprimento especificado?