Um aplicativo React Native é composto por dois lados, conforme mostrado abaixo.

  1. O lado do JavaScript
  2. O lado nativo

O lado nativo deve ser Java ou Kotlin para Android e Swift ou Objective-C para iOS.

A grande razão para a popularidade do React Native é que uma ponte pode ser criada entre o código JavaScript e a linguagem nativa. O React Native é desenvolvido de maneira que possamos produzir uma ponte entre o código JavaScript e a linguagem nativa. A ponte no React Native permite que o código JavaScript e o código nativo interajam entre si. Sem a ponte no React Native, não há absolutamente nenhum meio para o código nativo transmitir qualquer informação para o código JavaScript e vice-versa.

Necessidade de Bridge no React Native: Suponha que precisemos reutilizar algumas bibliotecas Java existentes sem implementá-las novamente em JavaScript. Assim, podemos reutilizá-lo em nosso aplicativo React Native com o uso do Native Bridge. Às vezes, para construir um aplicativo de nível de produção, provavelmente precisaremos usar o Native Bridge.

Trabalhando da ponte: Quando atingimos o ícone do nosso aplicativo para abrir nosso aplicativo, o sistema operacional projeta o thread principal (um thread de IU também conhecido como) e atribui esse thread ao nosso aplicativo. Este thread principal cria o thread JavaScript e o thread de sombra (também conhecido como árvore de sombra). A tarefa do thread de sombra é calcular os layouts descritos no lado do JavaScript e redirecionar esses detalhes para o lado nativo. As visualizações são definidas em JavaScript, computadas na árvore Shadow e redirecionadas para o thread de interface do usuário.

Despachando dados: agora sabemos como os layouts são descritos no início, mas o que acontece depois que o aplicativo começa a ser executado? o que acontece quando precisamos danificar um botão? Este detalhe é enviado pela ponte?

Para prejudicar um botão, podemos definir um recurso no lado do JavaScript que será redirecionado acima da ponte como um objeto JSON serializado. As melhorias nas visualizações nativas são agrupadas simultaneamente e redirecionadas para o lado nativo no final de toda a iteração do loop de eventos.

Junto com a transmissão de propriedades, podemos passar uma função que executará o código JavaScript como uma reação a vários eventos no lado nativo (como pressionar o botão). Observamos esse retorno de chamada em JavaScript, que fica serializado e redirecionado para o lado nativo. Quando pressionamos o botão, o evento nativo é redirecionado para o domínio JavaScript e o callback é realizado. Agora, também podemos redirecionar eventos do lado nativo para o lado do JavaScript diretamente, sem utilizar um retorno de chamada. O problema é que, se começarmos essa interatividade no lado nativo, não saberemos quem está prestando atenção ao lado do JavaScript, o que pode ativar etapas indesejadas e tornar nosso código difícil de depurar. Além disso, faz sentido fazer uso de retornos de chamada do lado JS, exceto por uma causa definida para não fazê-lo.

Execução: Na maioria das vezes todas as coisas passam continuamente, porém às vezes como uma ponte original ela obtém engarrafamentos. Quando há um grande catálogo de itens e começamos a rolar rapidamente, podemos reconhecer uma tela em branco antes que o resto dos itens sejam transmitidos. Isso acontece porque o evento nativo onScroll é redirecionado para o encadeamento JavaScript, o encadeamento JavaScript transmite os novos detalhes do layout para a árvore de sombra, a árvore de sombra calcula o layout e redireciona para o lado nativo. Enquanto rolamos rapidamente, reunimos esses eventos que dão origem a um congestionamento sobre a ponte. Podemos tentar escapar disso com layouts de pré-computação, a fim de cruzar a ponte algumas vezes. Ao executar animações complexas, podemos obter problemas de execução semelhantes. 

Vamos agora explorar em profundidade e reconhecer como o React Native funciona nos bastidores e isso nos ajudará a entender a compilação de JavaScript para um código nativo e o funcionamento de todo o procedimento. É importante reconhecer como todo o procedimento funciona, de modo que, às vezes, se você tiver problemas de desempenho, você reconhecerá de onde esse problema se origina.

Fluxo de informações: Como já discutimos, as ideias do React que potencializam o React Native, e ser uma delas é que a IU é uma função dos dados. Você pode converter a condição e o React percebe o que deve ser atualizado. Agora, suponhamos que os detalhes fluam junto com o aplicativo React normal. Explore o diagrama abaixo:

Explicação do diagrama acima:

  1. Temos uma seção React, que segue os detalhes para três seções filhas.
  2. O que está ocorrendo anonimamente é que uma árvore Virtual DOM é gerada, constituindo essas hierarquias de seção.
  3. Quando a condição da seção pai é atualizada, React avisa como proceder aos detalhes para os filhos.
  4. Como as crianças são principalmente uma representação da IU, React reconhece isso como agrupar as atualizações do DOM do navegador e implementá-las.

Agora, vamos desanexar o DOM do navegador e supor que, em vez de agrupar as atualizações do DOM do navegador, o React Native faça o mesmo com as chamadas aos módulos nativos. Portanto, os detalhes dos módulos nativos podem ser feitos de duas maneiras, que são fornecidas a seguir:

  1. Dados mutáveis ​​compartilhados
  2. Mensagens serializáveis ​​trocadas entre módulos JavaScript e nativos

O React Native usa o segundo método, que são mensagens serializáveis ​​trocadas entre os módulos JavaScript e Native. Em vez de alterar dados em objetos compartilháveis, ele continua mensagens agrupadas serializadas de forma assíncrona para o Bridge of React Native. A ponte no React Native é a camada que permite que o código JavaScript e o código Native interajam entre si.

Arquitetura: a seguir está o diagrama que explica a estrutura da arquitetura React Native:

React Native Architecture

Três camadas são indicadas no diagrama acima:

  1. JavaScript
  2. Ponte
  3. Nativo

A ponte no React Native é a camada que permite que os módulos JavaScript e Native interajam entre si e é principalmente uma camada de portadora que conduz mensagens de feedback agrupadas cronológicas não paralelas de JavaScript para módulos Native. Na imagem fornecida acima, a camada Nativa é mostrada por último, pois essa camada é a mais próxima do próprio dispositivo. 

Quando um incidente é implementado na camada nativa, pode ser um temporizador, toque ou solicitação de rede, principalmente, qualquer incidente que associe módulos nativos de dispositivo. Seus dados são montados e enviados para o React Native Bridge como uma mensagem serializada. Depois disso, o Bridge segue esta mensagem para a camada JavaScript.

A camada JavaScript é um loop de incidentes. Depois que o React Native Bridge prossegue com a carga útil serializada para o JavaScript, o incidente é processado e a lógica do aplicativo torna-se ativa.

Modelo de Threading: Agora, depois de todas as coisas que discutimos acima, é significativo reconhecer que todas as coisas discutidas acima são feitas em três threads principais:

  1. UI (thread principal do aplicativo)
  2. Módulos nativos
  3. Tempo de execução de JavaScript

Vamos entender sobre cada um dos tópicos acima:

  • A IU (thread principal do aplicativo): É a thread Native onde ocorre a percepção de nível nativo e é o lugar onde nossa plataforma de escolhas, como iOS ou Android, realiza desenho, estilização e medição.

  • Módulos nativos: se o aplicativo acessa qualquer API nativa, o acesso é feito em um thread de módulos nativos diferente. Por exemplo, se a câmera, local, fotos e qualquer outra API nativa for acessada, geralmente o arranjo e as indicações também são concluídas neste tópico.

  • Tempo de execução do JavaScript: é o thread em que cada código de aplicativo JavaScript será executado. Afinal, ele é baseado em um loop de incidente de JavaScript, portanto, é mais estável do que o thread de interface do usuário. Conseqüentemente, quando cálculos complicados são feitos em um aplicativo que realiza muitas alterações na interface do usuário, eles podem causar um desempenho ruim.