Intro
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 😉.
O que são High Order Components?
Assim como as High Order Functions o HOC é uma técnica que:
- Recebe um componente (função) como parâmetro e/ou retorna um novo componente
- É 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:
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:
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
Top comments (0)