Muitos engenheiros frontend provavelmente já passaram por aquele momento confuso em que seus componentes React ficam tão gigantescos que continuam perdendo o fio da ideia ao navegar pelo código do frontend. Para salvar a legibilidade, uma das práticas mais comuns é dividir os enormes componentes do React em partes menores. Tradicionalmente, eles faziam isso dividindo os elementos JSX. Esse método pode melhorar efetivamente a legibilidade dos componentes do React cuja única responsabilidade é exibir dados. No entanto, além de exibir dados, alguns componentes do React também são responsáveis por recuperar dados do backend. A maneira mais eficaz de tornar esses componentes do React legíveis é separá-los em Containers e Views. Neste artigo, vou demonstrar como dividir um componente do React em um Container e uma Visão com base no princípio da separação de preocupações.
O que são contêineres e vistas?
Primeiro, deixe-me esclarecer quais Containers e Views são responsáveis, respectivamente. Um componente 'Container' é responsável por buscar dados e manter o estado. Ele não se preocupa com a apresentação dos dados de forma alguma. Por outro lado, a responsabilidade exclusiva de um componente 'View' é exibir os dados. Ele não deve se preocupar com como recuperar os dados do backend.
Como você provavelmente já percebeu, há uma clara separação de preocupações entre os componentes 'Container' e 'View'. Essa abordagem ajuda a melhorar a legibilidade geral do código. Ao analisar os componentes 'Container', podemos nos concentrar em como recuperamos e atualizamos os dados. Ao analisar os componentes 'View', podemos focar muito na forma como apresentamos os dados aos nossos usuários.
Como dividir um componente em um 'contêiner' e uma 'vista'?
Nesta seção, vou demonstrar como dividir um componente React em um componente 'Container' e um componente 'View' com um exemplo simples. Digamos que tenhamos um componente em nível de página. Ele recupera informações do usuário do backend, exibe as informações do usuário e permite que os usuários mudem seu apelido.
importar { useEffect, useState } de 'react';
importar estilos de './UserPage.module.css';
importar { useEffect, useState } de 'react';
importar estilos de './UserPage.module.css';
type User = {
ID: Número;
Nome: corda;
Sobrenome: string;
E-mail: String;
avatarUrl: string;
Apelido: String;
};
tipo UserPageProps = {
userId: número;
};
função de exportação UserPage({ userId }: UserPageProps) {
const [usuário, setUser] = useState(null);
const [novoApelido, setNovoApelido] = useState('');
Quando passamos um array de dependência vazio para o gancho 'useEffect', ele só executará a função que passamos para ele uma vez após a criação do componente.
useEffect(() => {
fetch('/api/v1/users/${userId}', {
método: 'GET',
cabeçalhos: {
'Tipo de Conteúdo': 'application/json',
},
})
.then(res) => {
retorno res.json();
})
.then((usuário: Usuário) => {
setUser(user);
});
}, []);
const handleNicknameSubmit = () => {
setUser(null);
fetch('/api/v1/users/${userId}/apelido', {
método: 'POST',
cabeçalhos: {
'Tipo de Conteúdo': 'application/json',
},
corpo: JSON.stringify({
apelido: novoApelido,
}),
})
.then(res) => {
retorno res.json();
})
.then((usuário: Usuário) => {
setUser(user);
});
};
Usuário de retorno? (
<>
Primeiro Nome: {user.firstName}
Sobrenome: {user.sobrenome}
Apelido:
{
setNewNickname(e.target.value);
}}
/>
Enviar
) : (
Carregando...
);
}
Esse componente em nível de página faz primeiro uma solicitação 'GET' para '/api/v1/users/${userId}' para recuperar informações sobre o usuário atual em montagem. Em seguida, esse componente exibe as informações ao recebê-las. Esse componente também possui uma entrada para o usuário atual mudar seu apelido. Ele aciona uma solicitação 'POST' para '/api/v1/users/${userId}/nickname' para atualizar o apelido do usuário atual quando o usuário clica no botão 'Submit'.
Ao longo da minha carreira, vi muitos componentes em nível de página como este, alguns ainda mais complicados. Eles são abrangentes, e você pode encontrar tudo em um só lugar. No entanto, também é fácil se perder ao lê-los porque simplesmente acontece muita coisa no mesmo lugar.
Em seguida, vamos dividir esse componente em nível de página em um 'Container' e um 'View' para torná-lo mais legível.
importar { useEffect, useState } de 'react';
importar estilos de './UserPage.module.css';
importar { useEffect, useState } de 'react';
importar estilos de './UserPage.module.css';
type User = {
ID: Número;
Nome: corda;
Sobrenome: string;
E-mail: String;
avatarUrl: string;
Apelido: String;
};
tipo UserPageViewProps = {
usuário: Usuário;
novoApelido: corda;
setNovoApelido: (novoApelido: string) => vazio;
handleNicknameSubmit: () => void;
};
função UserPageView({
Usuário,
novoApelido,
setNovoApelido,
handleApelidoSubmit,
}: UserPageViewProps) {
retorno (
<>
Primeiro Nome: {user.firstName}
Sobrenome: {user.sobrenome}
Apelido:
{
setNewNickname(e.target.value);
}}
/>
Enviar
);
}
type UserPageContainerProps = {
userId: número;
};
função export UserPageContainer({ userId }: UserPageContainerProps) {
const [usuário, setUser] = useState(null);
const [novoApelido, setNovoApelido] = useState('');
useEffect(() => {
fetch('/api/v1/users/${userId}', {
método: 'GET',
cabeçalhos: {
'Tipo de Conteúdo': 'application/json',
},
})
.then(res) => {
retorno res.json();
})
.then((usuário: Usuário) => {
setUser(user);
});
}, []);
const handleNicknameSubmit = () => {
setUser(null);
fetch('/api/v1/users/${userId}/apelido', {
método: 'POST',
cabeçalhos: {
'Tipo de Conteúdo': 'application/json',
},
corpo: JSON.stringify({
apelido: novoApelido,
}),
})
.then(res) => {
retorno res.json();
})
.then((usuário: Usuário) => {
setUser(user);
});
};
if (!user) {
retorno Carregando...;
}
retorno (
);
}
Como você pode ver no código acima, extraímos o código para exibir informações do usuário e o transformamos em um novo componente 'View' chamado 'UserPageView'. Quanto à lógica para recuperar informações do usuário e fazer uma chamada API para mudar o apelido do usuário, mantivemos isso no componente original em nível de página que renomeamos para 'UserPageContainer'. Ao trabalhar no componente 'UserPageView', podemos focar nos dados que ele exibe e no estilo dos elementos. Ao ajustar 'UserPageContainer', não precisamos nos distrair com nada irrelevante para manutenção de estado ou para buscar e atualizar informações do usuário. No geral, fica mais fácil ler e refatorar o código frontend desta página.
Neste artigo, comecei definindo Containers e Views. Depois, expliquei por que dividir componentes do React em Containers e Views pode melhorar a legibilidade. Por fim, demonstrei como separar um componente do React em um Container e uma View, com um exemplo concreto. Pode ser demorado refatorar seus componentes do React com essa técnica, mas isso pode melhorar a eficiência do trabalho sua e dos seus colegas a longo prazo. Por favor, experimente essa técnica de refatoração quando tiver tempo!