Criando componentes mais testáveis e reutilizáveis no React usando o Single Responsibility Principle

Desenvolver componentes React testáveis e reutilizáveis é vital para construir aplicações sólidas e fáceis de manter. Neste artigo, vamos explorar como o Princípio da Responsabilidade Única (SRP) pode ser aplicado para criar componentes mais acessíveis e eficientes, utilizando exemplos práticos em um contexto real.

Componentes Puros

O que são Componentes Puros?

Componentes puros são como chefs especializados em uma única receita, focando em uma tarefa específica. Eles são claros, previsíveis e fáceis de entender. Vamos considerar um exemplo simples de um componente puro:

const CampoTexto = ({ label, valor, onChange }) => {
 return (
 <div> <label>{label}</label> <input type="text" value={valor} onChange={onChange} /> </div> );
};

Aqui, o componente “Contador” tem a única responsabilidade de exibir um valor e fornecer um botão para incrementá-lo.

Componentes Testáveis

O que é um Código Mais Fácil de Ser Testado?

Um código fácil de ser testado permite criar testes unitários eficientes. Testar componentes é essencial para garantir que o código funcione conforme o esperado. Vamos comparar isso com um código difícil de testar:

const FormularioLogin = ({ onLogin }) => {
 const [usuario, setUsuario] = useState("");
 const [senha, setSenha] = useState("");

 const handleSubmit = () => {
 // Realiza operações complexas, como validação e chamada de API
 // ...

 onLogin(usuario, senha);
 };

 return (
 <div> <CampoTexto label="Usuário" valor={usuario} onChange={(e) => setUsuario(e.target.value)} /> <CampoTexto label="Senha" valor={senha} onChange={(e) => setSenha(e.target.value)} /> <button onClick={handleSubmit}>Login</button> </div> );
};

O componente “ListaDeTarefas” pode ser difícil de testar devido às operações complexas que realiza. Testar a renderização da lista pode não ser suficiente para garantir seu correto funcionamento em diferentes situações.

A Dificuldade de Testar Componentes que Fazem Mais do que Lidar com a UI

Quando um componente lida com várias tarefas, como manipulação de estado, lógica de negócios e renderização de UI, torna-se complicado criar testes eficazes. A dependência de várias funcionalidades em um único componente pode levar a testes complexos e frágeis.

Refatorando um Componente de Login com o Princípio da Responsabilidade Única (SRP)

Vamos agora percorrer o processo de refatoração de um componente de login, inicialmente apresentando uma versão que não segue o SRP e expondo suas limitações. Em seguida, vamos criar uma versão otimizada utilizando o SRP.

Versão Não Otimizada

// Componente de login que mistura lógica e renderização
const FormularioLoginNaoOtimizado = ({ onLogin }) => {
 const [usuario, setUsuario] = useState("");
 const [senha, setSenha] = useState("");

 const handleSubmit = () => {
 // Lógica de validação e chamada de API misturada com manipulação de estado
 // ...

 onLogin(usuario, senha);
 };

 return (
 <div> <label>Usuário</label> <input type="text" value={usuario} onChange={(e) => setUsuario(e.target.value)} /> <label>Senha</label> <input type="password" value={senha} onChange={(e) => setSenha(e.target.value)} /> <button onClick={handleSubmit}>Login</button> </div> );
};

Problemas com a versão não otimizada:

  • Mistura de Lógica e Renderização: A lógica de validação e chamada de API está diretamente integrada à manipulação de estado e à renderização UI, tornando o componente difícil de testar e entender.

Versão Otimizada usando SRP

// Componente de login que mistura lógica e renderização
const FormularioLoginNaoOtimizado = ({ onLogin }) => {
 const [usuario, setUsuario] = useState("");
 const [senha, setSenha] = useState("");

 const handleSubmit = () => {
 // Lógica de validação e chamada de API misturada com manipulação de estado
 // ...

 onLogin(usuario, senha);
 };

 return (
 <div> <label>Usuário</label> <input type="text" value={usuario} onChange={(e) => setUsuario(e.target.value)} /> <label>Senha</label> <input type="password" value={senha} onChange={(e) => setSenha(e.target.value)} /> <button onClick={handleSubmit}>Login</button> </div> );
};

Vantagens da versão otimizada:

  • Responsabilidade Única: O “FormularioLoginLogic” cuida apenas da lógica do formulário, enquanto o “FormularioLoginUI” trata exclusivamente da renderização. Isso torna o código mais modular e fácil de entender.
  • Testabilidade Aprimorada: Ao separar claramente as responsabilidades, é mais fácil criar testes para a lógica do formulário sem se preocupar com a UI.
  • Reutilização Facilitada: A modularidade permite reutilizar a lógica do formulário em diferentes contextos, promovendo uma abordagem mais eficiente e escalável.

Ao adotar o SRP, não apenas melhoramos a estrutura do código, mas também facilitamos a manutenção e expansão do componente em projetos React do mundo real. Essa abordagem contribui para um código mais claro, conciso e robusto.

Quer aprender mais sobre SOLID e React? Clique aqui!