Created
February 5, 2026 13:25
-
-
Save isaacviannadev/862da45bf6f4fe845d64d3a2cdf30c57 to your computer and use it in GitHub Desktop.
SOLID on FE (React Examples)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SRP - Princípio da Responsabilidade Única | |
| // Errado: componente faz tudo | |
| function UserProfile() { | |
| const [user, setUser] = useState(null) | |
| useEffect(() => { fetch('/api/user').then(r => r.json()).then(setUser) }, []) | |
| if (!user) return <Spinner /> | |
| return <div>{user.name} - {formatDate(user.createdAt)}</div> | |
| } | |
| // Certo: cada um com sua responsabilidade | |
| function UserProfile() { | |
| const { user, isLoading } = useUser() | |
| if (isLoading) return <Spinner /> | |
| return <UserCard user={user} /> | |
| } | |
| --- | |
| // OCP - Princípio Aberto/Fechado | |
| // Errado: um if pra cada tipo | |
| function Alert({ type, message }) { | |
| if (type === 'success') return <div className="green">{message}</div> | |
| if (type === 'error') return <div className="red">{message}</div> | |
| if (type === 'warning') return <div className="yellow">{message}</div> | |
| } | |
| // Certo: extensível via configuração | |
| const alertStyles = { | |
| success: 'green', | |
| error: 'red', | |
| warning: 'yellow', | |
| } | |
| function Alert({ type, message }) { | |
| return <div className={alertStyles[type]}>{message}</div> | |
| } | |
| --- | |
| // LSP - Princípio da Substituição de Liskov | |
| // Errado: contratos diferentes entre componentes substituíveis | |
| <TextInput value={val} onChange={setVal} /> | |
| <SelectInput selected={val} onSelect={setVal} /> | |
| // Certo: mesmo contrato, substituíveis entre si | |
| <TextInput value={val} onChange={setVal} /> | |
| <SelectInput value={val} onChange={setVal} /> | |
| --- | |
| // ISP - Princípio da Segregação de Interface | |
| // Errado: hook que força dependência de tudo | |
| function useAuth() { | |
| return { user, token, login, logout, refresh, permissions, roles, sessions } | |
| } | |
| // Certo: interfaces segregadas | |
| function useUser() { return { user } } | |
| function usePermissions() { return { permissions, roles } } | |
| function useSession() { return { login, logout, refresh } } | |
| --- | |
| // DIP - Princípio da Inversão de Dependência | |
| // Errado: dependência direta da implementação | |
| import { analyticsService } from '@/services/analytics' | |
| function Button({ label }) { | |
| const handleClick = () => analyticsService.track('click', label) | |
| return <button onClick={handleClick}>{label}</button> | |
| } | |
| // Certo: dependência invertida via callback | |
| function Button({ label, onTrack }) { | |
| return <button onClick={() => onTrack?.('click', label)}>{label}</button> | |
| } | |
| // Quem decide a implementação é o pai, não o filho | |
| <Button label="Comprar" onTrack={(event, label) => ga.track(event, label)} /> | |
| <Button label="Comprar" onTrack={(event, label) => mixpanel.track(event, label)} /> | |
| <Button label="Comprar" /> // no teste: sem analytics nenhum |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment