Como gerenciar o React Data Grid através do Redux

Esta é uma continuação do artigo anterior: Por que escrever sua grade de dados do React em 2019


Para que serve o Redux? Existem muitas respostas. Por exemplo, para trabalhar com dados compartilhados em diferentes componentes do React. Mas você pode usar o Redux como uma maneira de manipular um componente. A aparência em si é interessante: qualquer componente React pode controlar outro componente React através do Redux.


Tome um componente React que exiba dados na forma de linhas e colunas (grade de dados, grade). Que funcionalidade ela pode gerenciar? A composição das colunas e linhas. Alocação. Seria bom rolar os dados.


imagem


Por exemplo, um determinado componente React (algum componente) pode gerenciar a grade assim:


  • exibir essas linhas e colunas;
  • destacar a ocorrência de tal palavra;
  • selecione essa linha;
  • vá até uma determinada linha.

Gerenciar colunas não é difícil. Basta colocar as configurações da coluna no Redux: nomes, ordem, larguras, mapeamento de dados. A grade utilizará essas configurações e aplicará. A abordagem de dados é a mesma.


Mas vamos complicar a tarefa. Suponha que haja muitas linhas. Eles não podem ser baixados do servidor de uma só vez e não podem ser exibidos de uma só vez. Portanto, é necessário o carregamento de dados em partes e o mapeamento de dados em porções.


Para exibição de parte, usamos a rolagem virtual descrita no artigo anterior . E tente atravessá-lo com o carregamento e armazenamento de partes no Redux. Também permitiremos que outros componentes manipulem os dados baixados e rolem a posição através do Redux.


Esta não é uma tarefa abstrata, mas uma tarefa real do sistema ECM que estamos desenvolvendo:
imagem


Organize os requisitos. O que você quer receber?


  • para que durante a rolagem, novos dados sejam carregados;
  • para que os dados carregados estejam no Redux;
  • para que as partes carregadas possam ser manipuladas de outros componentes. Por meio do Redux, adicione, exclua, modifique linhas e a grade captou essas alterações;
  • para que a posição de rolagem possa ser controlada de outros componentes. No Redux, role até a linha desejada.

Vamos considerar essas tarefas.


Uma pequena digressão: a rolagem virtual do artigo anterior permite rolar rapidamente para qualquer parte da grade. Por exemplo, no final. A grade deve carregar a parte mais recente dos dados, excluindo todos os intermediários, para não extrair milhares de linhas do servidor. Portanto, nem sempre as partes são carregadas sequencialmente; elas podem ser baixadas de diferentes partes da lista.


Escolhemos o seguinte esquema para carregar e armazenar dados:
imagem


A grade neste esquema é dividida em duas partes - componentes Presentational e Container. A apresentação lida apenas com a exibição de dados - essa é a visualização. Os dados são exibidos em páginas (isso foi descrito em um artigo anterior). O container é responsável por carregar os dados e interagir com o Redux.


Vamos percorrer as setas do diagrama:


  1. O Presentational não carrega dados, apenas informa por retorno de chamada quais dados faltam para exibir. O Presentational não conhece o Redux, não executa ações de despacho e não se conecta ao repositório do Redux.
  2. O contêiner é responsável por carregar os dados. Este componente envia uma solicitação ao servidor ao chamar o retorno de chamada. Um contêiner pode solicitar mais dados do que precisa exibir para minimizar o número de solicitações ao servidor.
  3. O servidor envia dados.
  4. O container envia os dados recebidos para o Redux. O Redux armazena todas as partes carregadas dos dados, não apenas a última parte carregada.
  5. Assim que os próximos dados chegarem ao Redux, o Container retirará todos os pedaços do Redux.
  6. E dê a eles uma apresentação. O Presentational não é necessário para desenhar todos os dados recebidos, ele exibe apenas o que cai na janela de exibição. Ao mesmo tempo, os dados carregados e as páginas renderizadas não são a mesma coisa. 1000 registros podem ser carregados em um bloco e 50 registros são exibidos em duas páginas.

Aqui está o pseudo-código deste circuito:


class GridContainer extends React.Component<Props> { props: Props; render(): React.Element<any> { return <Grid //     . dataSource={this.props.data} // Callback    . loadData={this.props.loadData} />; } } 

 const mapStateToProps = (state) => { return { data: state.data }; }; const mapDispatchToProps = (dispatch) => { return { loadData: async (skip: number, take: number) => { //    . const page: Page = await load(skip, take); //     Redux. dispatch({ type: ADD_PAGE, page }); } }; }; export default connect(mapStateToProps, mapDispatchToProps)(GridContainer); 

Tipos usados ​​no pseudocódigo:


 type Props = { data: DataSource, loadData: (skip: number, take: number) => void }; type DataSource = { //   . pages: Array<Page>, //    . totalRowsCount: number }; type Page = { // ,    . startIndex: number, // . rows: Array<Object> }; 

Eles lidaram com a primeira tarefa - carregar em parte e armazenar dados no Redux. Agora vamos para a manipulação. A tarefa mais comum é adicionar, excluir, modificar linhas. Queremos que todos os componentes do aplicativo da Web possam fazer isso. O esquema é simples:


imagem


Algum componente é um componente de um aplicativo da web que deseja gerenciar dados da grade.


Vamos seguir o esquema:


  1. Todas as manipulações de dados são realizadas através de redutores Redux. Para adicionar, excluir e alterar a linha, basta corresponder à ação correspondente (ADD_ROW, DELETE_ROW, UPDATE_ROW). Os redutores ajustam os dados no repositório Redux.
  2. Assim que os dados forem alterados no Redux, o Grid Container extrairá os dados atuais do Redux.
  3. E dê a eles uma apresentação. Atualizações de apresentação renderizadas páginas.

Percorrendo o Redux


Gerenciar a rolagem programaticamente é um recurso necessário. A situação mais comum é rolar para a entrada destacada. Por exemplo, o usuário cria uma nova entrada na lista. Um registro com classificação está no meio da lista. Você precisa selecioná-lo programaticamente e rolar para ele. E seria bom fazer isso através do Redux.


imagem


Gerenciar seleções através do Redux não é difícil, mas como você controla a rolagem?
Para fazer isso, na Redux Store, colocaremos dois campos:


  //  ,    . scrollToIndex: ?number, // ,    . scrollSignal: number 

O campo scrollToIndex é compreensível. Se você quiser rolar, defina o número da linha desejada em scrollToIndex. Esse número será transferido para a grade e a grade rolará imediatamente para ele:


imagem


Para que serve o campo scrollSignal? Ele resolve o problema de rolar novamente para o mesmo índice. Se já executamos a rolagem do software para o índice 100, a rolagem para o mesmo índice não funcionará novamente. Portanto, o campo scrollSignal é usado; quando alterada, a grade será rolada novamente para scrollToIndex. O ScrollSignal é incrementado automaticamente no redutor ao processar uma ação SCROLL:


imagem


Pseudo-código de controle de rolagem:


 class GridContainer extends React.Component<Props> { props: Props; render(): React.Element<any> { return <Grid //     . dataSource={this.props.data} //  ,    .. scrollToIndex={this.props.scrollToIndex} // ,    . scrollSignal={this.props.scrollSignal} />; } } 

 const mapStateToProps = (state) => { return { data: state.data, scrollToIndex: state.scrollToIndex, scrollSignal: state.scrollSignal }; }; export default connect(mapStateToProps)(GridContainer); 

Tipos usados ​​no pseudocódigo:


 type Props = { data: DataSource, scrollToIndex: ?number, scrollSignal: number }; 

Conclusão (por Redux)


Os esquemas de interação propostos com o Redux, é claro, não são universais. Eles são adequados para a grade que desenvolvemos, porque otimizamos a grade para esses esquemas e criamos a API apropriada. Esses esquemas não funcionarão para nenhuma grade de terceiros; portanto, considere o artigo como um exemplo de implementação de interação com o Redux.


Conclusão final (nos artigos 1 e 2)


Ao desenvolver nossa grade, entendemos que a grade, idealmente, não faz parte de nossa aplicação, mas um projeto independente, que vale a pena postar no github e em desenvolvimento. Portanto, não usamos os termos do assunto do nosso aplicativo no código e adicionamos dependências desnecessárias. Mas com a expansão da funcionalidade, está se tornando cada vez mais difícil aderir a isso, porque não a alocamos a um projeto separado, mas deveríamos ter feito isso imediatamente. O Github ainda está nos planos.


Escrever sua própria grade foi a decisão certa para nós. Tivemos tempo suficiente para implementar tudo o que queríamos (virtualização, trabalhando com redux, carregamento em lote, trabalhando com o teclado, trabalhando com colunas, pesquisa semelhante com luz de fundo e muito mais). Inicialmente, investimos fortemente em uma rede de terceiros, na esperança de que ela decolasse em nossas situações. Utilizando-o, entendemos como as redes funcionam em geral, quais problemas existem, como resolvê-los e o que queremos obter. E tomaram sua decisão.

Source: https://habr.com/ru/post/pt465585/


All Articles