Organizando a lógica de componentes em ReactJS

Organizando a lógica de componentes em ReactJS

Olá leitor, seja bem vindo a mais uma lição da jornada do desenvolvedor ReactJS 😄

A lição de hoje promete ser bem breve, onde pretendo explicar para vocês a forma como nós devemos organizar cada lógica existente dentro de um componente, desde a ordenação dos imports, estados, variáveis, returns e afins.

Preparado? Então vamos nessa!

A importância de ser um desenvolvedor organizado

Durante a sua jornada como desenvolvedor, muito dificilmente você vai entrar em uma "euquipe" ou em um "eutime", onde você é o único desenvolvedor de uma empresa ou de um projeto.

Caso este for o seu caso, boa sorte pra você 🤯 Pois já trabalhei em algumas empresas e projetos na qual só existia EU como desenvolvedor, e garanto para você que a experiência não é uma das melhores 😔

A maioria das empresas que trabalham com tecnologia, hoje já dispõem de uma equipe de pelo menos 3 ou mais desenvolvedores por projetos.

Isso significa que você não é o único desenvolvedor da equipe, logo, você precisa garantir que não só você como também o resto do seu time possa se "achar" dentro do seu código.

Ao longo dos anos, diversos materiais e livros foram lançados no mercado de TI com o objetivo de ajudar os desenvolvedores a escrever códigos melhores.

Destaco aqui dois deles:

Recomendo fortemente a leitura desses livros 😉

7 Razões para ser um desenvolvedor de software organizado

Abaixo eu separei 7 razões nas quais você precisa se tornar (ou continuar sendo) um desenvolvedor que se preocupa com a organização e a limpeza do seu código 🙃

Legibilidade do Código: Um código bem organizado é muito mais fácil de ler e entender. Isso é importante não apenas para você mesmo, mas também para outros membros da equipe que possam precisar revisar ou dar manutenção ao seu código no futuro.

Facilidade de Manutenção: Quando o código está organizado de forma lógica e clara, torna-se mais simples fazer alterações e corrigir bugs. Você pode localizar rapidamente as partes relevantes do código e entender como elas funcionam, o que reduz o tempo gasto na resolução de problemas.

Escalabilidade: Um código bem organizado é mais fácil de escalar. Conforme seu projeto cresce e você adiciona mais funcionalidades, é importante ter uma base sólida para evitar que o código se torne uma bagunça. A organização adequada facilita a adição de novos recursos e a expansão do projeto.

Reutilização de Código: A organização do código facilita a identificação de componentes e funções que podem ser reutilizados em diferentes partes do projeto ou até mesmo em projetos diferentes. Isso promove a eficiência no desenvolvimento, evitando a duplicação de código e incentivando a modularidade.

Colaboração Eficiente: Em um ambiente de equipe, a organização do código é essencial para facilitar a colaboração. Quando todos seguem as mesmas convenções e padrões de codificação, é mais fácil para os membros da equipe entenderem e contribuírem com o código uns dos outros de forma consistente.

Melhor Gerenciamento de Projetos: Um código bem organizado também facilita o gerenciamento do projeto como um todo. Você pode identificar rapidamente o progresso de diferentes partes do código, planejar futuras iterações e estimar prazos com mais precisão.

Qualidade do Software: Finalmente, a organização do código contribui para a qualidade geral do software. Um código bem organizado tende a ter menos erros e ser mais robusto, o que resulta em uma experiência melhor para o usuário final.

Dito isto, vamos aprender a organizar a lógica de nossos componentes 😋

Organizando as declarações em um componente no ReactJS

A organização das declarações em um componente em ReactJS, é uma prática importante para manter o código limpo, legível e fácil de dar manutenção por partes de outros membros da sua equipe.

Apesar de não haver uma regra de organização imposta pela própria linguagem ou framework (Javascript e ReactJS), o fato de você seguir uma convenção de organização pode ajudar bastante.

Como sugestão, vamos começar primeiro pelos imports!

Import

Durante as lições anteriores, nós vimos que os primeiros comandos que declaramos dentro de um componente são os import.

import React, {useState, useEffect} from 'react';
import './style.css';
import Home from './components/Home';

Legal, isso é um fato! Como via de regra os imports sempre devem ser declarados antes da declaração do componente principal.

Sendo assim, comece importando todos os módulos e componentes necessários. E Isso geralmente inclui os módulos do ReactJS, componentes personalizados, bibliotecas externas e quaisquer outros recursos necessários.

"Beleza, mas é só importar tudo isso de maneira avulsa?".

Apesar dessa ser uma possibilidade, eu recomendo que você siga a seguinte ordenação:

1) Imports de Bibliotecas Externas: Comece importando todas as bibliotecas externas necessárias. Isso inclui módulos do ReactJS, bibliotecas de roteamento (como React Router), gerenciamento de estado (como Redux), componentes de UI (como Material-UI), entre outros. Esses imports geralmente vêm de módulos instalados via npm ou yarn.

2) Imports de Componentes Personalizados: Em seguida, importe os componentes personalizados que você criou para o projeto. Isso inclui componentes ReactJS que estão localizados em outros arquivos do projeto, como é o caso daqueles que existem dentro da pasta src > components.

3) Imports de Estilos: Se você estiver usando arquivos de estilo separados (por exemplo, arquivos CSS ou SCSS), pode ser útil importá-los após os componentes. Isso ajuda a manter todos os imports relacionados ao estilo de forma agrupada.

4) Imports de Imagens e Outros Recursos Estáticos: Por fim, importe quaisquer imagens, fontes ou outros recursos estáticos que seu componente possa precisar. Esses imports geralmente são feitos usando caminhos relativos para os arquivos no sistema de arquivos do projeto.

Seguindo as dicas acima, teremos algo parecido com isso:

// Imports de Bibliotecas Externas
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';

// Imports de Componentes Personalizados
import App from './App';
import Header from './components/Header';
import Footer from './components/Footer';

// Imports de Estilos
import './index.css';
import './styles/custom.scss';

// Imports de Imagens e Outros Recursos Estáticos
import logo from './assets/logo.png';
import font from './assets/font.ttf';

//Daqui pra baixo já começa a declaração do seu componente...

Variáveis de Estado (useState)

Após a declaração dos imports e também do seu componente, logo abaixo das chaves que abrem a função anônima do seu componente:

const MeuComponente = () => {
 //Logo aqui na primeira linha...
}

É o local onde devemos declarar todas as nossas variáveis, isso antes de qualquer função, hook, ou return.

Sendo assim sempre comece definindo as variáveis que não possuem seus estados controlados, seguindo daquelas que possuem seus estados controlados, por exemplo:

const MeuComponente = () => {

 //Variáveis sem estado
 const variavel = 'Micilini';
 const site = 'https://micilini.com';

 //Variáveis com estado
 const {nome, setNome} = useState('');
 const {idade, setIdade} = useState(22);

}

Note que no código acima, primeiro declaramos as variáveis comuns seguida das variáveis de estado.

Portanto, podemos concluir que, se o componente tiver variáveis de estado (state), é útil declará-las logo após os imports(dentro do seu componente) Isso inclui o uso do useState para definir variáveis de estado locais.

Variáveis de Referência (useRef)

Em seguida, como via de regra, o ideal é que façamos as declarações das nossas variáveis de referência, as famosas useRef.

Sendo assim, se o seu componente precisar de referências a elementos do DOM ou outros elementos, você pode declará-las após as variáveis de estado.

Por exemplo:

const MeuComponente = () => {

 //Variáveis sem estado
 const variavel = 'Micilini';
 const site = 'https://micilini.com';

 //Variáveis com estado
 const {nome, setNome} = useState('');
 const {idade, setIdade} = useState(22);

 //Variáveis de referência
 const rank = useRef("");
 const level = useRef("");
}

Funções auxiliares

Em seguida, declaramos todas as funções auxiliares que estão presentes dentro do nosso componente.

Desde um handleClick, handleSubmit ou qualquer outra função que é chamada pelo componente. Por exemplo:

const MeuComponente = () => {

 //Variáveis sem estado
 const variavel = 'Micilini';
 const site = 'https://micilini.com';

 //Variáveis com estado
 const {nome, setNome} = useState('');
 const {idade, setIdade} = useState(22);

 //Variáveis de referência
 const rank = useRef("");
 const level = useRef("");

 //Funções Auxiliares
 const handleClick = () => {
 console.log('O usuário clicou...');
 }

 const handleSubmit = (e) => {
 e.preventDefaul();
 alert('Formulário Enviado!');
 }
}

Funções auxiliares são todas as funções que trabalham com a manipulação de dados, funções de validação, funções de chamadas de API e etc.

Hooks de Efeito

Se o componente precisar de efeitos colaterais, como buscar dados de uma API ou subscrever eventos, use o useEffect para declarar essas ações.

Isso vai mantér todas as operações de efeito agrupadas em um lugar conveniente.

Sendo assim, após a declaração das funções auxiliares, declare todos os seus useEffect.

const MeuComponente = () => {

 //Variáveis sem estado
 const variavel = 'Micilini';
 const site = 'https://micilini.com';

 //Variáveis com estado
 const {nome, setNome} = useState('');
 const {idade, setIdade} = useState(22);

 //Variáveis de referência
 const rank = useRef("");
 const level = useRef("");

 //Funções Auxiliares
 const handleClick = () => {
 console.log('O usuário clicou...');
 }

 const handleSubmit = (e) => {
 e.preventDefaul();
 alert('Formulário Enviado!');
 }

 //Hooks de Efeito
 useEffect(() => {
 console.log('UseEffect sendo executado!');
 }, [])
}

Corpo do Componente

Por fim, e não menos importante, declaramos o return do nosso componente 😊

const MeuComponente = () => {

 //Variáveis sem estado
 const variavel = 'Micilini';
 const site = 'https://micilini.com';

 //Variáveis com estado
 const {nome, setNome} = useState('');
 const {idade, setIdade} = useState(22);

 //Variáveis de referência
 const rank = useRef("");
 const level = useRef("");

 //Funções Auxiliares
 const handleClick = () => {
 console.log('O usuário clicou...');
 }

 const handleSubmit = (e) => {
 e.preventDefaul();
 alert('Formulário Enviado!');
 }

 //Hooks de Efeito
 useEffect(() => {
 console.log('UseEffect sendo executado!');
 }, [])

 // Componente Principal
 return (
 <div>
 <h1>My Component</h1>
 <ChildComponent data={data} />
 </div>
 );
}

Se o seu componente usufrui de renderizações condicionais nas quais existam mais de um return, basta declará-los sempre após o useEffect.

E é claro, sem esquecer do export default no final do arquivo:

export default MeuComponente;

Exemplo de um projeto organizado

Se você aplicou todas as dicas acima, no final você terá algo parecido com isso:

// Imports de Bibliotecas Externas
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';

// Imports de Componentes Personalizados
import App from './App';
import Header from './components/Header';
import Footer from './components/Footer';

// Imports de Estilos
import './index.css';
import './styles/custom.scss';

// Imports de Imagens e Outros Recursos Estáticos
import logo from './assets/logo.png';
import font from './assets/font.ttf';

//Daqui pra baixo já começa a declaração do seu componente...

const MeuComponente = () => {

 //Variáveis sem estado
 const variavel = 'Micilini';
 const site = 'https://micilini.com';

 //Variáveis com estado
 const {nome, setNome} = useState('');
 const {idade, setIdade} = useState(22);

 //Variáveis de referência
 const rank = useRef("");
 const level = useRef("");

 //Funções Auxiliares
 const handleClick = () => {
 console.log('O usuário clicou...');
 }

 const handleSubmit = (e) => {
 e.preventDefaul();
 alert('Formulário Enviado!');
 }

 //Hooks de Efeito
 useEffect(() => {
 console.log('UseEffect sendo executado!');
 }, [])

 // Componente Principal
 return (
 <div>
 <h1>My Component</h1>
 <ChildComponent data={data} />
 </div>
 );
}

export default MeuComponente;

Viu como ficou mais simples e super organizado? 😋

Conclusão

Nesta lição você aprendeu sobre a importância de se organizar os comandos do seu componente junto a prática.

Até a próxima lição!