詳細検索

Separação de Preocupações: Divida seus componentes do React em contêineres e visualizações

Avatar
por Chen Ziyu
5 min de leitura

Separação de Preocupações: Divida seus componentes do React em contêineres e visualizações
Traduzido do English • Ver original

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!

Related Articles