DEV Community

Marlon Marques
Marlon Marques

Posted on

MVVM com Factory no React Native

Recentemente encontrei um vídeo muito bom falando sobre Arquitetura MVVM no React Native. Realmente é um assunto que não é muito abordado na comunidade React/React-Native. O que acaba tornando o conteúdo abordado de grande importância.

Portanto, a proposta deste conteúdo é trazer um complemento sobre a abordagem do Padrão de Arquitetura MVVM utilizando o Padrão de Projeto Factory.

Diferente do MVP (Model-View-Presenter), o MVVM (Model-View-ViewModel) traz uma proposta onde deixamos o tratamento das informações para o ViewModel, um pouco parecido com o Presenter. No entanto, a grande diferença é, enquanto o Presenter do MVP conhece a View e tem o papel de "apresentar". No MVVM o ViewModel tem o papel de também conter o tratamento das informações, porém, ele não conhece a View, ocorrendo o contrário, a View conhecendo o ViewModel, ou vários ViewModel's.

Feita a introdução, vamos ao ponto que eu quero chegar. É comum "injetarmos" o ViewModel diretamente na nossa View utilizando o MVVM. E isso me incomoda um pouco, portanto, vamos utilizar o padrão de projeto Factory para desacoplarmos a implementação do ViewModel da nossa View.

Eu aproveitei o excelente conteúdo apresentado no video e fiz um fork do repositório para realizarmos as nossas alterações.

A primeira coisa a ser feita é removermos o useLoginViewModel que estava sendo usado diretamente dentro da nossa View. Como podemos ver no código abaixo:

import useLoginViewModel from './view.model';

const LoginView: React.FC = () => {
  const {email, password, setEmail, setPassword, isLoading, onSubmit} =
    useLoginViewModel();
};
Enter fullscreen mode Exit fullscreen mode

Vamos receber o loginViewModel via props, como o useLoginViewModel retornava o tipo LoginViewModel, então a alteração será mínima. Portanto:

  • Recebemos loginViewModel via props;
const LoginView: React.FC<Props> = ({loginViewModel}) => {
  const {email, password, setEmail, setPassword, isLoading, onSubmit} =
    loginViewModel;
};
Enter fullscreen mode Exit fullscreen mode
  • Agora vamos definir um tipo para o loginViewModel, como já mencionado o useLoginViewModel retornava um tipo LoginViewModel, logo:
type Props = {
  loginViewModel: LoginViewModel;
};
Enter fullscreen mode Exit fullscreen mode

Bem, isso feito. Vamos criar o nosso Factory que vai realizar a composição das dependências, ou seja, vamos passar o nosso loginViewModel via props para a nossa View.

import React from 'react';
import LoginView from '../../../pages/login/view';
import useLoginViewModel from '../../../pages/login/view.model';

const loginViewFactory: React.FC = () => {
  const loginViewModel = useLoginViewModel();

  return <LoginView loginViewModel={loginViewModel} />;
};

export default loginViewFactory;
Enter fullscreen mode Exit fullscreen mode

Por fim, agora basta usar o nosso LoginFactory na raiz do App, em vez do LoginView.

import React from 'react';
import LoginFactory from './helpers/factories/login/view.factory';

const App: React.FC = () => {
  return <LoginFactory />;
};

export default App;
Enter fullscreen mode Exit fullscreen mode

E é isso pessoal, com essa abordagem, conseguimos desacoplar da nossa View o ViewModel, passando apenas o tipo LoginViewModel via props, deixando totalmente independente da implementação utilizando um Factory. Ah, e os testes estão passando normalmente sem necessidade de alterações.

Caso tenha interesse em ver o código: https://github.com/MarlonBeloMarques/mvvm-factory-with-react-native

Valeu galera, até a próxima.

Top comments (5)

Collapse
 
colaquecez profile image
Filipe Colaquecez • Edited

Bacana a abordagem, porém passar os hooks diretamente para uma única view vejo que teria renders desnecessários, sempre que o loginViewModel for alterado o seu LoginView irá renderizar toda a árvore, ou seja qualquer alteração que houver do hook

const loginViewModel = useLoginViewModel(); 
Enter fullscreen mode Exit fullscreen mode

Irá renderizar tudo dentro do LoginView.

Collapse
 
marlonbelomarques profile image
Marlon Marques

Sim, realmente é um ponto a se considerar. Porém, se fossemos usar diretamente dentro da View, o impacto seria o mesmo, não? Talvez refinando melhor a ideia, acredito que chegamos em uma solução melhor.

Collapse
 
colaquecez profile image
Filipe Colaquecez

Se for usado diretamente dentro da View dependendo de como fossse feito teriamos o mesmo problema mesmo, porém se fosse usado um useMemo por exemplo, dessa forma tendo uma única View não funcionária, pq temos uma única prop responsável por todas as props.

Thread Thread
 
marlonbelomarques profile image
Marlon Marques • Edited

Exatamente, realmente é algo que pode ser investigado para ver se serial possível com essa abordagem de ViewModel.

Thread Thread
 
colaquecez profile image
Filipe Colaquecez

Sim total, no nativo temos essas facilidades, talvez irá ter uma evolução no React que nos permita aplicar essas arquiteturas.