react-flow-app
react-light-form

🚀 Biblioteca React.js com o objetivo de simplificar as navegações com foco em eventos (ações do utilizador) para facilitar as integrações.

Principais funcionalidades:

  • 🤳 Baseado em eventos (ações do utilizador)
  • 📦 Modularização da Aplicação
  • ⚙️ Centralizado na configuração para gestão das navegações
  • 🔃 Maior reutilização
  • 🧩 Integração simplificada (ex: envio de dados analíticos)
  • 🔐 Total controlo das navegações
  • 💯 Suporte para Typescript
  • 🔄 Carregamento parcial (lazy loading)
  • 💻 Desenvolvimento com Intellisense


⚒️ 1. API

ℹ️ 1.1. useFlow

Hook que permite aceder a um conjunto de métodos e propriedades para agilizar as navegações.

Para ter acesso a todos os métodos, nomeadamente ao dispatch, é necessário passar como parâmetro a configuração do ecrã.

Abaixo são descritos os respetivos métodos e propriedades disponibilizadas.

📍 1.1.1. back

Permite navegar para o último ecrã, de acordo com a configuração do fluxo corrente.

Posteriormente será abordado com mais detalhe e exemplos em concreto.

const { back } = useFlow(flowManager.screens.screen1);

...

// chamar para voltar para o ecrã anterior (quando existe)
back();

📍 1.1.2. dispatch

Permite indicar a ação/evento a despachar (de acordo com a configuração), nomeadamente as ações definidas para o respetivo screen passado no parâmetro do useFlow.

const { dispatch } = useFlow(flowManager.screens.screen1);

...

dispatch('<action_name>');

📍 1.1.3. getCurrentStep

Permite obter o passo atual.

const { getCurrentStep } = useFlow(flowManager.screens.screen1);

...

getCurrentStep();

📍 1.1.4. getHistory

Permite obter um array de passos que ficaram armazenados no histórico e na qual é possível voltar.

const { getHistory } = useFlow(flowManager.screens.screen1);

...

getHistory();

📍 1.1.5. getLastAction

Permite obter a última ação realizada no flow actual.

const { getLastAction } = useFlow(flowManager.screens.screen1);

...

getLastAction();

📍 1.1.6. getPreviousStep

Permite obter o passo anterior.

const { getPreviousStep } = useFlow(flowManager.screens.screen1);

...

getPreviousStep();

📍 1.1.7. hasPreviousStep

Permite verificar se existe passo anterior, retornando true em caso de existir e false nos restantes casos.

const { hasPreviousStep } = useFlow(flowManager.screens.screen1);

...

hasPreviousStep();

📍 1.1.8. refresh

Permite forçar a atualização do passo/ecrã que está a ser visualizado.

const { refresh } = useFlow(flowManager.screens.screen1);

...

refresh();

ℹ️ 1.2. useFlowManager

Hook que tem como objetivo disponibilizar a interação com os fluxos.

📍 1.2.1 start

Permite inicializar um fluxo.

const { start } = useFlowManager();

...

start(flows.flow1.start());

ℹ️ 1.3. FlowManager

Permite criar a instância do flowManager a usar na Aplicação (deve ser usada sempre esta instância para aceder aos ecrãs).

📍 1.3.1. flow

Método que permite a criação de fluxos, com a respetiva indicação dos passos que compõem o fluxo.

ℹ️ 1.4. FlowProvider

Provider que permite agilizar todas as navegações, necessitando que seja passada uma instância do flow manager.



🧑🏼‍💻 2. Exemplos

De seguida são elencados os passos necessários para o correto funcionamento da biblioteca.

2.1. Configuração dos ecrãs

Necessário definir as 3 propriedades seguintes:

  • name: nome do ecrã
  • actions: array de ações que o ecrã disponibiliza, ações estas que ficaram disponíveis no respetivo ecrã para fazer o respetivo trigger da navegação
  • loader: função que irá permitir carregar o respetivo ecrã (é recomendado o uso de lazy loading)
// file: screens/index.tsx
import React from 'react';
import { FlowManager } from 'react-flow-app';

const screens = {
	screen1: {
		name: 'screen1',
		actions: ['next', 'skip'],
		loader: () => React.lazy(() => import('./screen1/screen1')),
	},
	screen2: {
		name: 'screen2',
		actions: ['confirm'],
		loader: () => React.lazy(() => import('./screen2/screen2')),
	},
} as const;

export const flowManager = new FlowManager(screens);

2.2. Ecrãs

// file: screens/screen1/screen1.tsx
import React from "react";
import { useFlow } from "react-flow-app";
import { flowManager } from "..";

const Screen1: React.FC = () => {
  const { dispatch } = useFlow(flowManager.screens.screen1);

  return <>
    <h1>Screen 1 example</>
    <button onClick={() => {
      dispatch('next');
    }}>Next</button>
    <button onClick={() => {
      dispatch('skip');
    }}>Skip</button>
  </>
};

export default Screen1;
// file: screens/screen2/screen2.tsx
import React from "react";
import { useFlow } from "react-flow-app";
import { flowManager } from "..";

const Screen2: React.FC = () => {
  const { dispatch } = useFlow(flowManager.screens.screen2);

  return <>
    <h1>Screen 2 example</>
    <button onClick={() => {
      dispatch('confirm');
    }}>Confirm</button>
  </>
};

export default Screen2;

2.3. Fluxos

// file: flows/flow1.tsx
import { flowManager } from "@screens";

export const flow1 = flowManager
  .flow({ name: "flow1", baseUrl: "flow1" })
  .steps({
    screen1: {
      initialStep: true,
    },
    screen2: {},
  });

hub.step("screen1")({
  next: "screen2",
  skip: () => {
    // executar qualquer js que seja pretendido
  },
});

hub.step("screen2")({
  confirm: "screen1",
});

// integração com terceiros, exemplo: Google Tag Manager, Firebase, etc

// ver ecrã
hub.listen({
  callback: ({ currentStepName }): void => {
    // enviar dados
  },
  type: "mount",
});

// enviar evento
hub.listen({
  callback: ({ currentStepName, dispatch }): void => {
    if (dispatch) {
      const { actionName, payload } = dispatch;

      // enviar dados
    }
  },
  type: "dispatch",
});
// file: flows/flow2.tsx
import { flowManager } from "@screens";
import { flow1 } from "./flow1";

export const flow2 = flowManager
  .flow({ name: "flow2", baseUrl: "flow2" })
  .steps({
    screen1: {},
    screen2: {
      initialStep: true,
      clearHistory: true,
    },
  });

hub.step("screen1")({
  next: "screen2",
  skip: () => {
    return flow1.navigateTo();
  },
});

hub.step("screen2")({
  confirm: () => {
    return flow1.navigateTo();
  },
});

// integração com terceiros, exemplo: Google Tag Manager, Firebase, etc

// ver ecrã
hub.listen({
  callback: ({ currentStepName }): void => {
    // enviar dados
  },
  type: "mount",
});

// enviar evento
hub.listen({
  callback: ({ currentStepName, dispatch }): void => {
    if (dispatch) {
      const { actionName, payload } = dispatch;

      // enviar dados
    }
  },
  type: "dispatch",
});

2.4. App

// src/index.tsx
import { FlowProvider } from 'react-flow-app';
import { flowManager } from '@screens';

...

<FlowProvider fm={flowManager}>
  <App />
</FlowProvider>

...
// src/app.tsx
import { useFlowManager } from 'react-flow-app';
import { flow1 } from '@flows';

...
const { start } = useFlowManager();


React.useEffect(() => {
  start(flow1.start());
}, []);

...


🖥️ 3. Demo



🔥 4. Trabalho Futuro

  • dev tools