Executando verificação de segurança...
1

Você ja ouviu falar nos High Order Components?

Introdução

Fala galera, tudo beleza? Hoje vou explicar um conceito considerado um tópico intermediario/avançado e bastante utilizado por algumas libs no React e React Native, os chamados High Order Components, nesse post vou te mostrar qual problema eles resolvem e como implementa-los 😉.

Obs: no fim desse post tem um link para um vídeo onde eu explico os mesmo conceitos!

O que são High Order Components?

Assim como as High Order Functions o HOC é uma técnica que:

  1. Recebe um componente (função) como parâmetro e/ou retorna um novo componente
  2. É util para se reutilizar a lógica de um componente, reforçando o DRY (Don't Repeat Yourself no seu código)

Caso Problema

Imaginemos o seguinte caso: um aplicação simples que tem dois componentes que são "populados" através de uma API - O nome e cargo do usuário, dessa forma:

Caso problema

A lógica dentro de cada componente é a seguinte:

NameBox.tsx

import * as React from 'react';

interface NameBoxProps {
	data: string | null;
}
 

function NameBox({ data }: NameBoxProps) {

if (!data) {
	<div style={{ backgroundColor: 'gray', width: 120, height: 120 }}>
		<p>Carregando...</p>
	</div>;
}

return (

	<div style={{ backgroundColor: 'green', width: 120, height: 120 }}>
		<p>{data}</p>
	</div>

	);

	}
export default NameBox;

JobBox.tsx

import * as React from 'react';

interface JobBoxProps {
	data: string | null;
}

function JobBox({ data }: JobBoxProps) {

	if (!data) {
		<div style={{ backgroundColor: 'gray', width: 120, height: 120 }}>
			<p>Carregando...</p>
		</div>;
	}

	return (

		<div style={{ backgroundColor: 'orange', width: 120, height: 120 }}>
			<p>{data}</p>
		</div>

	);

}

export default JobBox;

Basicamente é um componente que recebe uma propriedade chamada data e a exibe dentro de uma tag div, se data não tiver um valor verdadeiro, o componente exibe a frase 'Carregando'.

Como no exemplo abaixo:

Gif com o funcionamento

Bom, o que temos de problema aqui?

Estamos utilizando a mesmissima lógica para exibir o status de "Carregando..." em dois lugares diferentes.

E agora você pode pensar:

Que tal, criarmos um componente de e chama-lo nos dois componentes?

Seu pensamento está correto, criando um novo componente de loading conseguimos abstrair um pouco mais nosso código, deixando ele mais reutilizavél e com uma manutenção um pouco mais fácil, porém a lógica a seguir ainda seria repetida nos dois componentes:

...

if (!data) {
	<Loading/>
}

...

Bom, e como conseguimos resolver isso de uma maneira super elegante? Exatamente, com High Order Components!

Criando um High Order Component

Como eu disse lá no começo, um HOC é um componente que recebe um componente como parâmetro e retorna um novo componente, e é examente isso que vamos fazer:

Primeiro criamos um arquivo chamado withLoader.tsx

e dentro dele vamos criar um componente que recebe um componente como parâmetro e retorna outro componente (é bastante componente eu sei...) desta forma:

import * as React from 'react';

const withLoader = (Component: React.ElementType) => (props: any) => {
	return <Component {...props} />
};

export default withLoader;

Desta forma temos acesso ao componente e as props que ele tem.

A última coisa que temos que fazer por aqui é verificarmos se nossa propriedade data existe , se existir retornamos o Componente que está sendo passado como parâmetro, se não retornamos nossa div com o "Carregando..."

Ficando dessa fora:

import * as React from 'react';

const withLoader = (Component: React.ElementType) => (props: any) => {

	return !props.data ? (

		<div style={{ backgroundColor: 'gray', width: 120, height: 120 }}>
			<p>Carregando...</p>
		</div>
	) : (
		<Component {...props} />
	);
};

export default withLoader;

Pronto, agora nossa lógica de exibição e componente de carregamento estão em um lugar só, mas como fazer com que os componentes JobBox.tsx e NameBox.tsx se utilizem disso?

Basta chamar o withLoader passando nosso componente como função:

import * as React from 'react';

interface NameBoxProps {
	data: string | null;
}

function NameBox({ data }: NameBoxProps) {
	return (
	<div style={{ backgroundColor: 'green', width: 120, height: 120 }}>
		<p>{data}</p>
	</div>
	);
}

// Passamos o NameBox como parâmetro do nosso HOC withLoader
export default withLoader(NameBox);

E pronto, agora temos um High Order Component em uso! Deixando nosso código bem mais modularizado, melhorando a reutilização e manutenção do nosso código.

Libs que utilizam High Order Components

Segue algumas libs que usam HOCs e que você talvez não tenha percebido, ou não sabia do que se tratava

  • Redux (React)
  • Apollo (React)
  • Code Push (React Native)
  • React Navigation (React Native)

Conclusão

Vimos que High Order Components são excelentes para respeitarmos o DRY e modularizarmos nosso código, que sua implementação nem é tão complicada assim como o nome faz parecer e que eles são excelentes para resolvermos alguns problemas do dia-a-dia.

Se você quiser ver esse mesmo conteúdo em formato de vídeo, entre nesse link, tenho feito videos de vários padrões de JS e React focados no front-end!

Até a próxima!

Link do projeto no StackBlitz: https://react-ts-9f1nvy.stackblitz.io
Canal no Youtube: Everaldev - YouTube

Carregando publicação patrocinada...
1

Opa, eu já tinha ouvido falar desses carinhas, mas não lembrava de uma aplicação, e a sua é super simples e prática! Mas uma dúvida, eu já ouvi que eles era muito usados quando o react só tinha componentes classe, mas hoje com componentes funcionais, eu acho que os hooks seria uma aplicação melhor, procede isso?

2

Fala mano! Sim, o objetivo do post era mostrar como funcionava mesmo, pra quando a galera se deparar com ele no código pudesse ter uma noção do que ta rolando!
Mas hoje ainda existem algumas aplicações em que HOCs e HOFs são ideais.

Alguns exemplos que trabalho no dia a dia são:

1
1

Concordo mano! Mas ainda existem casos em que um HOC/HOF são mais aplicáveis que hooks, deixei alguns exemplos no comentário ali em cima!

1

Você colocou exemplos de bibliotecas que não receberam updates. Ok, se você quer usar bibliotecas que não estão sendo atualizadas para os novos padrões mas no meu dia-a-dia eu não crio um novo HOC faz anos e não uso faz anos também.

Idem para class componentes.