DEV Community

Terminal Coffee
Terminal Coffee

Posted on • Updated on

5 Dicas de uso do método map

No nosso artigo anterior exploramos como as diferenças entre os métodos de arrays, dizendo que eles podem ser úteis no dia-a-dia, entretanto não nos aprofundamos muito em detalhes para nenhum deles, por isso hoje vamos ver 5 dicas para você parar de usar o map só naqueles exemplos de incrementar os números de um array!

# 01 - Usar para fazer o cast de tipo

Para a nossa primeira dica vamos ver como podemos usar o map para rapidamente converter todos os valores de um array para determinado tipo. Para isso podemos usar os construtores dos valores primitivos do JS: String, Number, e Boolean.

Eles são funções também, e por isso podem ser utilizados para converter os valores de um array no tipo correspondente, ex:

const numbers = [1, 2, 3];
const strings = numbers.map(String);
const numbersAgain = strings.map(Number);
const booleans = numbersAgain.map(Boolean);
Enter fullscreen mode Exit fullscreen mode

# 02 - Usar para aplicar um Adapter em um array de objetos

Podemos usar ele em um array de objetos em favor de pegar só uma propriedade em específico, ex:

const people = [
  { name: 'John Doe', age: 20 },
  { name: 'Jane Doe', age: 22 },
  { name: 'Fulano de Tal', age: 18 }
];

const names = people.map(({ name }) => name);
Enter fullscreen mode Exit fullscreen mode

Um conjunto delas:

const people = [
  { name: 'John Doe', age: 20, country: 'USA' },
  { name: 'Jane Doe', age: 22, country: 'USA' },
  { name: 'Fulano de Tal', age: 18, country: 'Brazil' }
];

const namesAndAges = people.map(({ name, age }) => ({
  name,
  age
}));
Enter fullscreen mode Exit fullscreen mode

Ou aplicar o padrão de projetos adapter em si:

class Post {
  constructor(title, content) {
    this.title = title;
    this.content = content;
  }
}

class ApiPostAdapter extends Post {
  constructor(apiPost) {
    super(apiPost.title, apiPost.body);
  }

  static from(apiPost) {
    return new ApiPostAdapter(apiPost);
  }
}

fetch("api/posts")
  .then(response => response.json())
  .then(posts => posts.map(ApiPostAdapter.from));
Enter fullscreen mode Exit fullscreen mode

Assim sendo uma ferramenta bem útil para manipular as informações de um objeto, adaptando elas para cada formato que for sendo necessário na aplicação, o que é particularmente útil quando você tem que traduzir entre objetos e DTOs, por exemplo, ao ter que adaptar os dados do banco de dados em um objeto de domínio, e transformar os objetos de domínio em view models que serão utilizados pelas views do seu sistema.

# 03 - Atualizar um valor no array

Podemos usar o map para atualizar um valor em específico do array, ao usar um if dentro dele, e retornando o item atual caso não entre no nele, ex:

const people = [
  { name: 'John Doe', age: 20, country: 'USA' },
  { name: 'Jane Doe', age: 22, country: 'USA' },
  { name: 'Fulano de Tal', age: 18, country: 'Brazil' }
];

const updated = people.map(person => {
  if (person.name === 'Jane Doe') {
    return {
      ...person, // copia os dados atuais dela
      age: 17 // declare de novo as propriedades que vão ser atualizadas
    };
  }

  return person;
});
Enter fullscreen mode Exit fullscreen mode

Isso é mais útil do que se pode imaginar quando você tem que lidar com situações onde tem que programar usando imutabilidade, como no React por exemplo.

Essa é uma operação bem útil, então podemos até ter uma função utilitária que faz ela para nós:

function updateBy(array, predicate, update) {
  return array.map(item => predicate(item) ? update(item) : item);
}
Enter fullscreen mode Exit fullscreen mode

Ela poderia ser escrita sem o parâmetro predicate, mas ai não poderíamos escrever um critério customizado para dizer se o item deve ser atualizado ou não.

# 04 - Rodar promises em paralelo

Promises representam computações assíncronas, e a maior vantagem delas é que você pode rodar todas ao mesmo tempo ao invés de uma atrás da outra, e assim ganhar performance quando isso é possível.

Por exemplo, é muito comum que APIs que implementam o estilo HATEOAS devolvam apenas os ids, talvez algumas informações básicas, e links de navegação ao acessarmos endpoints de listagem ao invés de uma lista completa dos dados, então para listar todos os dados completos é necessário fazer uma requisição para esse endpoint, e depois fazer uma requisição para cada item e só então podemos montar a lista toda, ex:

const list = await fetchList();
const completeList = [];

for (const item of list) {
  completeList.push(await fetchItemById(item.id));
}
Enter fullscreen mode Exit fullscreen mode

Um padrão que vimos no post sobre métodos de iteração, com um adicional que todas as requisições vão rodar em serial ao invés de rodarem ao mesmo tempo, para fazer elas rodarem ao mesmo tempo, podemos usar o map em conjunto com o Promise.all, ex:

const list = await fetchList();
const completeList = await Promise.all(list.map(({ id }) => fetchItemById(id)));
Enter fullscreen mode Exit fullscreen mode

# 05 - Chamar a mesma função várias vezes com parâmetros diferentes

Apesar disso parecer óbvio quando entendemos que o map recebe uma função e produz um novo array com base nela, entretando como a gente foca muito nos dados, essa possibilidade simples pode acabar passando batida.

Uma coisa comum quando estamos desenvolvendo é chamar a mesma função várias vezes seguidas apenas trocando os seus parâmetros, o que leva a um certo grau de duplicação de código, por exemplo, ao usar repetidas vezes o document.querySelector:

const form = document.querySelector("form");
const input = document.querySelector("input");
const error = document.querySelector("span");

// lógica para validar o formulário e mostrar os erros
Enter fullscreen mode Exit fullscreen mode

Nesse caso, podemos notar que o document.querySelector foi repetido para cada elemento sendo selecionado, e teria que ser novamente caso precisassemos de mais itens, uma forma de eliminar essa duplicação poderia ser utilizando o map, ex:

const [form, input, error] = ['form', 'input', 'span'].map(selector => {
  return document.querySelector(selector);
})
Enter fullscreen mode Exit fullscreen mode

Aqui convertemos cada parâmetro utilizado nas chamadas individuais em um array, ai é só utilizar o map para aplicar a função em cada parâmetro que voila, temos o mesmo resultado só que sem a repetição no nosso código, seguindo bem o princípio DRY.

Conclusão

Espero que tenha gostado do artigo de hoje, não se esqueça de compartilhar com outras pessoas que ainda não descobriram as maravilhas do map caso tenha gostado, e até a próxima.

ASS: O Suporte Cansado

Top comments (0)