Embora tenha sido concebido para a programaรงรฃo orientada a objetos, os princรญpios do SOLID podem ser aplicados em outros contextos como em componentes React.
- Este post aborda o “O” do S[O]LID
- Criado com Next 13 + React 18
- Codepen no final do post
- A aplicaรงรฃo inicia com o SRP aplicado
OCP – Open-Closed Principle
O Open Closed Principle (Princรญpio Aberto/Fechado) preconiza que uma entidade de software (classe, mรณdulo, funรงรฃo, etc.) deve estar aberta para extensรฃo (ou seja, deve ser possรญvel adicionar novos comportamentos ou funcionalidades sem modificar o cรณdigo existente) e fechada para modificaรงรฃo (ou seja, o cรณdigo existente nรฃo deve ser modificado para adicionar novos comportamentos ou funcionalidades).
Suponha que temos uma lista de usuรกrios que podem ser exibidos em um componente em nossa aplicaรงรฃo. Inicialmente, exibimos apenas o primeiro nome e o gรชnero do usuรกrio com um รญcone ao lado do nome, sendo azul para usuรกrios masculinos e vermelho para usuรกrios femininos.
No contexto de componentes, o princรญpio Aberto/Fechado nรฃo estรก sendo aplicado ao cรณdigo fornecido. Isso ocorre porque o componente ListUsersBefore precisa ser alterado se houver a necessidade de adicionar um filtro de usuรกrios, componentes ou propriedades dentro dele. Isso viola o princรญpio, pois o componente deve estar aberto para extensรฃo e fechado para modificaรงรฃo.
/**
* ocp
* ListUsersBefore
* hooks
* useUsers
* index.ts
* index.tsx
* styles.ts
*/
Componente principal:
//ocp/ListUsersBefore/index.tsx
import { FaFemale, FaMale } from 'react-icons/fa';
import { useUsers } from './hooks/useUsers';
import { S } from './styles';
export const ListUsersBefore = () => {
const { data, isLoading } = useUsers();
return (
<>
{isLoading && <div>Loading...div>}
{data.map((user) => (
<S.Div
gender={user.gender}
key={user.email}
>
{(user.gender === 'female' && <FaFemale />) || <FaMale />}
<span>{user.name.first}span>
S.Div>
))}
>
);
};
Estilos do componente principal:
//ocp/ListUsersBefore/styles.ts
type StyledUserProps = {
gender: 'male' | 'female';
};
export const S = {
Div: styled.div<StyledUserProps>`
color: ${(props) => (props.gender === 'male' ? 'blue' : 'red')};
border: 1px solid;
max-width: 200px;
padding: 0.2rem;
margin-bottom: 0.2rem;
border-radius: 4px;
`
};
Hook que fornece os dados:
//ocp/ListUsersBefore/hooks/useUsers/index.tsx
import axios from 'axios';
import { useEffect, useState } from 'react';
type User = {
name: {
first: string;
};
email: string;
gender: 'male' | 'female';
};
type useUsersReponse = {
data: User[];
isLoading: true | false;
error: null | string;
};
export const useUsers = (): useUsersReponse => {
const [data, setData] = useState<User[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<null | string>(null);
const handleFetch = async () => {
setIsLoading(true);
try {
const url = `https://randomuser.me/api/?results=5`;
const res = await axios.get(url);
setError(null);
setData(res.data.results);
} catch (err) {
setError('Error get Users!');
}
setIsLoading(false);
};
useEffect(() => {
handleFetch();
}, []);
return {
data,
isLoading,
error
};
};