Introdução
A componentização é um dos pilares fundamentais do React. Ela permite dividir a interface em partes menores, independentes e reutilizáveis, facilitando a manutenção, a escalabilidade e a legibilidade do código. No projeto Text Decoder Challenge, utilizamos essa abordagem para organizar a interface de codificação e decodificação de textos de maneira eficiente.
O Que é Componentização?
Componentização é o processo de dividir a interface do usuário em componentes. Cada componente encapsula uma funcionalidade específica, tornando o código mais modular. No React, os componentes funcionam como funções JavaScript, que aceitam "props" (propriedades) e retornam elementos que descrevem o que deve ser renderizado na tela.
No Text Decoder Challenge, cada parte da interface – o input de texto, os botões de codificar e decodificar, e o campo de exibição dos resultados – é um componente separado. Isso torna o código mais fácil de gerenciar e possibilita a reutilização desses componentes em diferentes contextos.
Propriedades (Props) e Estado (State)
Os props são valores passados de um componente pai para um componente filho. Eles são imutáveis, ou seja, o componente filho não pode modificá-los diretamente. Essa passagem de dados é essencial quando queremos que um componente exiba ou utilize informações que vêm de outro componente. No Text Decoder Challenge, usamos props para passar o texto digitado pelo usuário ao componente de decodificação. Por exemplo:
<Input
id="inputtextDecodificador"
value={inputValue}
onChange={handleInputChange}
placeholder="Digite um texto que deseja decodificar"
/>
Aqui, o valor da entrada de texto (inputValue) é passado como prop para o componente Input. O componente pai (no caso, Decoder) controla o estado do valor através do state e o distribui ao filho via props.
O state é um dado que o componente gerencia internamente e que pode ser alterado ao longo do tempo. No React, quando o state é atualizado usando a função setState, fornecida pelo hook useState, o componente é re-renderizado automaticamente para refletir as mudanças. No nosso projeto, o estado armazena o texto codificado ou decodificado, e toda vez que ele é alterado, o React atualiza a interface. O uso do state pode ser visto neste trecho:
const [inputValue, setInputValue] = useState('');
Aqui, (inputValue) é o estado atual, e (setInputValue) é a função usada para alterar esse estado. Cada vez que o usuário digita algo no campo de texto, a função handleInputChange chama (setInputValue) para atualizar o valor.
const handleInputChange = (e) => {
setInputValue(e.target.value);
};
Isso garante que a interface reaja dinamicamente às ações do usuário.
Exemplo Prático: Desafio do Decodificador de Texto
O Text Decoder Challenge permite que o usuário insira um texto e escolha entre codificar ou decodificar a mensagem. O projeto também fornece a opção de copiar o texto que deseja realizar a criptografia ou descriptografia para a área em que será realizada a codificação ou decodificação. A seguir, a estrutura básica do projeto, com componentes para cada parte essencial da interface:
No projeto original, identificamos componentes como:
Header: Um componente que exibe o cabeçalho da aplicação.
Input: Um componente reutilizável para entrada de texto.
Button: Um componente genérico para botões, esta sessão engloba a lógica de codificação e decodificação.
Decoder: A seção em que é possível inserir o texto que será decodificado.
Aplicando a Componentização
Identificação de Componentes
A estrutura do projeto já foi organizada de forma a utilizar componentes. Aqui estão os principais componentes identificados:
Input: Campo de entrada de texto, que pode ser reutilizado em diferentes partes do projeto.
Button: Um componente reutilizável para criar diferentes botões (por exemplo, "Codificar", "Decodificar", "Copiar").
Decoder: Seção que contém a lógica de copiar o texto que deseja codificar e a interação do usuário.
Componentes Detalhados
Decoder.js - Este componente contém a estrutura da interface, onde o usuário interage com o decodificador.
import React, { useState } from "react";
import { Input } from "../Input/Input";
import { Button } from "../Button/Button";
import text_decoder from "../../assets/text-decoder.png";
import styles from "./Decoder.module.css";
export function Decoder() {
const [inputValue, setInputValue] = useState('');
const [copySuccess, setCopySuccess] = useState('');
function handleCopyText() {
let textToCopy = document.querySelector('#inputtextDecodificador').value;
navigator.clipboard.writeText(textToCopy).then(() => {
setCopySuccess('Texto copiado com sucesso!');
}).catch(err => {
console.error('Ops, ocorreu um erro ao copiar o texto!');
});
}
const handleInputChange = (e) => {
if (e.target.value !== inputValue) {
setInputValue(e.target.value);
}
};
return (
<section className={styles.container__decoder}>
<div className={styles.content__text__decoder}>
<img src={text_decoder} alt="Decodificador de Texto" />
<h1 className={styles.title__text_decoder}>Nenhuma mensagem encontrada</h1>
<Input
id="inputtextDecodificador"
value={inputValue}
onChange={handleInputChange}
placeholder="Digite um texto que deseja decodificar"
className={styles.input__text__decoder}
/>
<Button
id="inputcopytext"
onClick={handleCopyText}
label="Copiar"
aria-label="Copiar o texto inserido"
className={styles.copy__button}
/>
{copySuccess && <p className={styles.copyMessage}>{copySuccess}</p>}
</div>
</section>
);
}
Input.js - Um componente genérico para campos de entrada de texto.
import React from "react";
import styles from "./Input.module.css";
export function Input({ id, value, onChange, placeholder }) {
return (
<input
id={id}
value={value}
onChange={onChange}
placeholder={placeholder}
className={styles.container__text__input}
/>
);
}
Button.js - Um componente para os botões de interação.
import React from "react";
import styles from "./Button.module.css";
export function Button({ id, onClick, label, className }) {
return (
<>
<button
id={id}
className={className === "encrypt__button" ? styles.encrypt__button : styles.decrypt__button}
onClick={onClick}
>
{label}
</button>
</>
);
}
Componente App: Integração de Componentes e Uso de State e Props
O componente App é o ponto central onde todos os componentes são integrados e onde a lógica do projeto é gerenciada. Ele organiza o fluxo da aplicação, utilizando o state para armazenar o valor de entrada do texto e os eventos de codificação e decodificação. O uso de props permite que os dados sejam passados para os componentes filhos, como o Input e o Button.
import React, { useState } from "react";
import { Header } from "./components/Header/Header";
import { Input } from "./components/Input/Input";
import { Button } from "./components/Button/Button";
import { Decoder } from "./components/Decoder/Decoder";
import bi_exclamation from "./assets/bi_exclamation-circle-fill.png";
import styles from "./App.module.css";
import "./styles/global.css";
function App() {
const [inputValue, setInputValue] = useState('');
const handleInputChange = (e) => {
setInputValue(e.target.value);
};
function handleEncrypt() {
let textoDigitado = document.querySelector('#inputtext1').value;
const encryptedText = textoDigitado.split('').map(char =>
String.fromCharCode(char.charCodeAt(0) + 1)
).join('');
document.querySelector('#inputtext1').value = encryptedText;
}
function handleDecrypt() {
let textoDigitado = document.querySelector('#inputtext1').value;
const decryptText = textoDigitado.split('').map(char =>
String.fromCharCode(char.charCodeAt(0) - 1)
).join('');
document.querySelector('#inputtext1').value = decryptText;
}
return (
<div>
<Header />
<main className={styles.container_main}>
<section className="container_text">
<Input
id="inputtext1"
value={inputValue}
onChange={handleInputChange}
placeholder="Digite seu texto"
className={styles.container__text__input}
/>
<div className={styles.container__info__type__text}>
<div className={styles.content__info__type__text}>
<img
src={bi_exclamation}
alt="Aviso do tipo de texto a ser inserido no input"
/>
<p className={styles.paragraph__info__type__text}>
Apenas letras minúsculas e sem acento.
</p>
</div>
</div>
<div className={styles.btn}>
<Button
id="codificador"
label="Criptografar"
onClick={handleEncrypt}
className={styles.encrypt__button}
/>
<Button
id="descriptografar"
label="Descriptografar"
onClick={handleDecrypt}
className={styles.decrypt__button}
/>
</div>
</section>
<Decoder />
</main>
</div>
);
}
export default App;
Como o App Integra os Componentes?
State e Input: O state armazena o valor do texto digitado no campo de entrada, que pode ser atualizado dinamicamente conforme o usuário interage com o campo.
Props e Button: As funções de onClick do botão de codificação e decodificação são passadas como props para os componentes Button. Isso permite que o botão acione as funções diretamente no componente pai (App), mantendo a lógica centralizada.
Componente Decoder: Além dos botões e do campo de texto, o componente App também integra o Decoder, que lida com a cópia de texto, reforçando o conceito de componentização e reutilização de componentes.
Com isso, o componente App conecta todos os blocos do projeto, centralizando a lógica e distribuindo as responsabilidades para os componentes especializados. A utilização de props e state garante uma interação fluida entre os componentes e a interface de usuário.
Benefícios da Componentização no Projeto
Reutilização: Componentes como os botões de codificar e decodificar podem ser reutilizados em diferentes partes do projeto ou até em outros projetos.
Facilidade de manutenção: Alterar a lógica de um componente afeta apenas aquele bloco específico, sem impactar o resto do código.
Clareza e organização: A separação de responsabilidades em componentes menores torna o código mais legível e fácil de entender.
Conclusão
A componentização no Text Decoder Challenge transforma a interface, tornando-a mais modular e escalável, promovendo reutilização e clareza. Ao usar props e state de maneira estratégica, garantimos uma experiência de usuário dinâmica e fluida, mantendo o código organizado e eficiente. Essa abordagem é essencial para a construção de interfaces de alta qualidade no React.
Bibliografia
Documentação: https://pt-br.react.dev/blog/2023/03/16/introducing-react-dev
Rocketseat: https://blog.rocketseat.com.br/react-do-zero-componentizacao-propriedades-e-estado/