3
respostas

[Dúvida] Criar componentes reaproveitáveis

Olá um bom ano novo (2026), para todos!

Desde a primeira aula foi enfatizado o desenvolvimento de componentes "reaproveitáveis" entretanto, cada componente que criamos possui um import do estilo CSS fixo e não dinâmico, o que impede o reaproveitamento do componente em outras partes do projeto ou em outros projetos.

Pensei que a respeito e concluí que o componente filho deveria receber por parâmetro do componente pai o nome da classe que deveria ser utilizada e a importação do estilo CSS deveria ser realizada pelo componente pai, pois este conhece o contexto em que será utilizado o componente filho e por isso ele é capaz de informar a classe CSS para o componente filho.

Gostaria que fosse apresentado uma orientação a respeito, conforme práticas mais utilizadas.

Está sendo tratado neste posto os assuntos das aulas 1 e 2 do curso "React: Desenvolvendo com Javascript".

3 respostas

Olá, Eduardo. Feliz ano novo.

Esse ponto que você levantou é bem comum quando estamos migrando do mental model de HTML + CSS para o de componentes em React, então vale ajustar essa forma de pensar agora.

A ideia central é: componentes não são tags HTML customizadas. No React, o componente é a unidade de estrutura, comportamento e estilo. Ele não deve depender do contexto externo para existir corretamente.

Abaixo vou separar em não faça e faça, com exemplos práticos.

Não faça: o pai decide o estilo do filho

Quando o componente filho recebe uma className obrigatória para funcionar, ele passa a conhecer o contexto do pai indiretamente. Isso cria acoplamento estrutural.

// Filho
function Button({ className, children }) {
  return (
    <button className={className}>
      {children}
    </button>
  )
}

// Pai
import './dashboard.css'

function Dashboard() {
  return (
    <Button className="dashboard-primary-button">
      Salvar
    </Button>
  )
}

Problemas dessa abordagem:

  • O Button não é mais uma unidade fechada
  • Ele depende de CSS externo para funcionar corretamente
  • Cada novo contexto precisa conhecer a implementação interna do componente
  • A reutilização vira reutilização de CSS, não de componente

Esse modelo é muito parecido com HTML + CSS tradicional, apenas com funções.

Faça: o componente define sua própria identidade

Aqui o componente conhece sua estrutura e seu estilo. O CSS é um detalhe interno.

// Button.jsx
import './button.css'

function Button({ children }) {
  return (
    <button className="button">
      {children}
    </button>
  )
}
/* button.css */
.button {
  padding: 8px 16px;
  border-radius: 4px;
}

Agora o componente:

  • É previsível
  • Não depende do pai
  • Pode ser reutilizado em qualquer lugar sem conhecimento extra

Faça: variações sem acoplamento (props semânticas)

Quando precisamos de variações, não passamos classes, e sim intenção.

function Button({ variant = 'primary', children }) {
  return (
    <button className={`button button--${variant}`}>
      {children}
    </button>
  )
}
<Button variant="primary">Salvar</Button>
<Button variant="danger">Excluir</Button>

O pai informa o que quer, não como o CSS funciona.

Faça: composição em vez de controle externo

Quando o problema é estrutura, a solução é composição.

function Card({ children }) {
  return <div className="card">{children}</div>
}

function CardHeader({ children }) {
  return <div className="card-header">{children}</div>
}

function CardContent({ children }) {
  return <div className="card-content">{children}</div>
}
<Card>
  <CardHeader>Título</CardHeader>
  <CardContent>Conteúdo</CardContent>
</Card>

Cada componente:

  • Conhece apenas sua responsabilidade
  • Não depende de classes externas
  • Pode ser reorganizado sem quebrar contratos

Sobre className

Passar className não é proibido, mas também não é a regra.

Normalmente usamos quando:

  • Estamos criando componentes extremamente genéricos
  • Estamos integrando com bibliotecas externas
  • Existe um motivo claro para abrir esse ponto de extensão

Nas aulas 1 e 2, a escolha consciente é não fazer isso, justamente para reforçar:

  • Encapsulamento
  • Composição
  • Independência entre componentes

O ajuste principal aqui é mental:

Não pense em reaproveitar CSS.
Pense em reaproveitar comportamento e estrutura através de componentes.

Esse é o passo de pensar como React, e não apenas escrever React.

Vinicios, obrigado pela orientação.

De sua resposta, entendi que o componente deve existir sem qualquer dependência.

Mas se necessitar dar ao componente a possibilidade de customização, seguindo a sugestão "props semânticas", a seguinte implementação seria correta ou pode ser melhorada?

/* src/index.css */
/* @inicio, ícones */
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined');

/* Opcional: Estilo para facilitar o uso dos ícones */
.material-symbols-outlined {
  font-variation-settings: 'FILL' 1, 'wght' 100, 'GRAD' -25, 'opsz' 24;
  vertical-align: middle;
}
/* @fim */

/* abaixo outros estilos do projeto */
...
/* src/componentes/Botao/index.js */
import './Botao.css';

const Botao = (props) => {
    return (
        <button className={`botao botao--${props.variant}`}>
            {/* O ícone vem antes do children */}
            <span className="material-symbols-outlined">save</span>
            {props.children}
        </button>
    )
};

export default Botao;
/* src/componentes/Botao/Botao.css */
.botao {
    background-color: var(--cor-customizada, grey);
    border-radius: 10px;
    font-weight: 700;
    font-size: 18px;
    padding: 32px;
    border: none;
    cursor: pointer;
    color: #fff;
    margin: 32px 0;

    /* adiciona um espaço entre os elementos dentro do botão */
    /* display: inline-flex; */
    display: block;
    gap: 10px;
}

.botao:hover {
    color: #95ffd4;
}

/* customizar a cor do botão conforme a necessidade*/
.botao--primary {
  --cor-customizada: #6278f7;
}

.botao--danger {
  --cor-customizada: red;
}
/* src/componentes/Formulario/index.js */
<Botao variant="primary">
    Criar Card
</Botao>

<Botao variant="danger">
    Excluir Card
</Botao> 

Salve o/

Boa pergunta — e sim, você entendeu corretamente a ideia central: o componente precisa existir por conta própria, sem depender de quem está usando ele.

A abordagem com variant está no caminho certo. Quando você escreve algo como:

<button className={`botao botao--${props.variant}`}>

E usa o componente assim:

<Botao variant="primary">Criar Card</Botao>
<Botao variant="danger">Excluir Card</Botao>

O pai não está dizendo como o botão deve ser estilizado. Ele está dizendo qual é a intenção. O detalhe de como isso vira CSS continua sendo responsabilidade do componente. Esse é exatamente o papel das props semânticas.

Tem um detalhe pequeno, mas importante. Se alguém usar o botão sem passar a variant:

<Botao>Salvar</Botao>

A classe gerada será algo como:

botao botao--undefined

Nada quebra, mas o componente deixa de ser previsível. Uma melhoria simples é definir um valor padrão:

const Botao = ({ variant = 'primary', children }) => {
  return (
    <button className={`botao botao--${variant}`}>
      {children}
    </button>
  )
}

Agora o botão funciona sozinho, mesmo que o pai não configure nada.

Agora sobre o ícone... uma solução comum é passar o ícone por prop (icon="save"). Funciona, mas existe uma abordagem ainda mais elegante: composição.

Idealmente o Botao não sabe o que é um ícone. Ele apenas renderiza o que vier dentro dele.

const Botao = ({ variant = 'primary', children }) => {
  return (
    <button className={`botao botao--${variant}`}>
      {children}
    </button>
  )
}

Uso:

<Botao variant="primary">
  <IconPlus />
  Add
</Botao>

Ou:

<Botao variant="danger">
  <IconTrash />
  Excluir
</Botao>

Desse jeito:

  • o botão não conhece ícones
  • não existe acoplamento com biblioteca visual
  • o pai decide a composição, não o estilo

O CSS continua sendo responsabilidade do botão, inclusive o alinhamento interno:

.botao {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

Sobre o index.css e a importação da fonte de ícones: isso está no lugar certo. Fonte, ícones e variáveis globais são infraestrutura da aplicação. O componente não precisa saber de onde isso vem, apenas que existe uma classe responsável por renderizar o símbolo.

No fim das contas, as duas abordagens existem, mas composição costuma ser a mais flexível a longo prazo. Você mantém o componente fechado, simples e preparado para crescer.

Eu escrevi uma série de 5 artigos sobre SOLID e componentes React, acho que podem te ajudar no seu estudo. Dá um confere aqui, são 5 no total. Um pra cada princípio. Tá bem alinhada com a nossa conversa aqui.