DEV Community

Cover image for React na Prática: Componentes controlados ou não Controlados
Alvaro Guimarães
Alvaro Guimarães

Posted on • Edited on

React na Prática: Componentes controlados ou não Controlados

Controlled vs Uncontrolled

Uma decisão importante que afeta bastante na qualidade do seu código é determinar onde o estado de um componente deve residir, e esta decisão impacta diretamente a flexibilidade, reusabilidade e complexidade.

Um exemplo clássico desta decisão é a implementação de um modal: deve ele gerenciar seu próprio estado de visibilidade ou delegar este controle ao componente pai?

Componentes Controlados: Delegando o Controle

Em um componente controlado, o estado é gerenciado externamente pelo componente pai.

Esta abordagem oferece maior flexibilidade e permite que o componente pai coordene múltiplos estados relacionados.

Nessa abordagem, podemos dizer que a flexibilidade do Modal é alta, mas a
responsabilidade sobre ele também é, pois, o componente pai precisa manter a lógica necessária para abrir e fechar o modal.

// Exemplo de Modal controlado: export function Modal({ isOpen, onChangeIsOpen, children }) { // O componente recebe o estado como prop e delega mudanças através de callbacks return ( <dialog open={isOpen} onClose={() => onChangeIsOpen(false)} > {children} </dialog> ); } // Exemplo de uso: export function App() { const [isOpen, setIsOpen] = useState(false); return ( <div> <Modal isOpen={isOpen} onChangeIsOpen={setIsOpen}> <p>Greetings, one and all!</p> <button onClick={() => setIsOpen(false)}>OK</button> </Modal> <button onClick={() => setIsOpen(true)}>Open Modal</button> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Componentes Não Controlados: Autonomia Interna

Por outro lado, componentes não controlados mantêm e gerenciam seu próprio estado internamente. Esta abordagem reduz a complexidade do componente pai e é ideal quando o comportamento do componente pode ser encapsulado de forma independente.

// Exemplo de modal não controlado: export function Modal({ children, onOpenChange }) { const [isOpen, setIsOpen] = useState(false); const handleOpenChange = (newState) => { setIsOpen(newState); onOpenChange?.(newState); // Opcional: notifica o pai sobre mudanças }; if (!isOpen) { return ( <button onClick={() => handleOpenChange(true)}>Open Modal</button> ); } return ( <dialog open onClose={() => handleOpenChange(false)} > {children} <button onClick={() => handleOpenChange(false)}>OK</button> </dialog> ); } // App.tsx function App() { return ( <Modal onOpenChange={(isOpen) => console.log('Modal state:', isOpen)}> <p>Greetings, one and all!</p> </Modal> ); } 
Enter fullscreen mode Exit fullscreen mode

Esta decisão de design influencia diretamente a manutenibilidade e reusabilidade do seu código.

Use componentes controlados quando:

  • O componente pai precisa coordenar múltiplos estados relacionados
  • Você precisa de controle preciso sobre o comportamento do componente
  • O estado do componente precisa ser sincronizado com outras partes da aplicação

Use componentes não controlados quando:

  • O comportamento do componente é independente do resto da aplicação
  • Você quer reduzir a complexidade do componente pai
  • O componente pode funcionar de forma autônoma

Top comments (0)