React-window: Alterações da versão 2

Criado em 29 jul. 2019  ·  44Comentários  ·  Fonte: bvaughn/react-window

Esta é uma questão abrangente para compartilhar meus planos para o próximo lançamento da versão 2.0 de react-window .

Comentários são apreciados e serão levados em consideração. Peço que você compreenda se eu não for capaz de atender a todas as solicitações. Vou tentar fazer o meu melhor para pesar as solicitações de recursos em relação ao tamanho do pacote, desempenho de tempo de execução e questões de manutenção.

Espero que a atualização da versão 1 para a 2 possa exigir mudanças substanciais no código , muitas das quais não serão possíveis de automatizar com mods de código. Por causa disso, particularmente para o código do aplicativo, eu desaconselho a atualização do código existente, a menos que você tenha um forte motivo (por exemplo, você precisa de suporte para conteúdo de tamanho dinâmico).

Também irei fixar os documentos atuais no domínio react-window-v1.now.sh para que não sejam perdidos quando eu atualizar para a versão 2.


Índice:
  • Suporta menos componentes
  • Usar API de renderização
  • Não há mais suporte para listas horizontais
  • Apenas grades suportam RTL
  • Mudanças no tempo de retorno de chamada onScroll

    * Outras mudanças / depreciações

Menos componentes

Uma maneira de ajudar a gerenciar a complexidade é reduzir o número de componentes que a biblioteca suporta . No momento, estou planejando oferecer suporte apenas aos seguintes tipos de componentes na versão 2:

  • SimpleList (anteriormente FixedSizeList )

    • Este componente de lista altamente otimizado deve ser usado quando as alturas das linhas são fixas (e conhecidas com antecedência).

  • List (anteriormente DynamicSizeList )

    • Esta lista deve ser usada para conteúdo de tamanho dinâmico (por exemplo, chat, feed de notícias). Requer a API ResizeObserver (ou polyfill).

  • Grid (anteriormente VariableSizeGrid )

    • Este componente deve ser usado para dados tabulares (por exemplo, planilhas) que devem ser virtualizados ao longo dos eixos vertical e horizontal. Ele oferece suporte a linhas e colunas de tamanho variável, mas não oferece suporte à medição e atualização automática de seus tamanhos.


Renderizar adereços

Uma das principais mudanças de react-virtualized para react-window foi a decisão de tratar children como elementos React (por exemplo, React.createElement(children, props)) ) em vez de recursos de render (por exemplo children(props) ).

Houve algumas motivações para fazer isso:

  • React fornece soluções integradas para memoização (por exemplo, React.memo , useMemo , shouldComponentUpdate ), portanto, não precisei implementar minha própria abstração de cache para representantes de itens.
  • APIs como ganchos e suspense "simplesmente funcionam" dentro dos representantes de itens.
  • As chaves podem ser gerenciadas por react-window sem exigir que o prop de renderização as repasse (e sem exigir cloneElement chamadas).

Infelizmente, também houve algumas desvantagens:

  • Os representantes de itens embutidos incorrem em um alto custo. Como seu "tipo" (a definição de função) é recriado cada vez que o componente pai é renderizado, o React desmonta e remonta profundamente sua árvore renderizada. Isso significa que os documentos precisam ensinar as pessoas a não usá-los, embora sejam geralmente mais convenientes.
  • Como as funções inline não podiam ser usadas para fechar no escopo local, era mais complicado para os representantes de itens compartilharem o estado com os pais, exigindo APIs como itemData e uma exportação de comparação personalizada areEqual .

Depois de levar em consideração os prós e contras acima, decidi converter para uma abordagem de adereços de renderização para react-window também. Isso significa que exemplos complicados como este podem ser reescritos mais facilmente:

const Example = ({ height, items, toggleItemActive, width }) => (
  <List
    height={height}
    itemCount={items.length}
    itemRenderer={({ index, key, style }) => {
      const item = items[index];
      return (
        <div key={key} onClick={() => toggleItemActive(index)} style={style}>
          {item.label} is {item.isActive ? "active" : "inactive"}
        </div>
      );
    }}
    itemSize={35}
    width={width}
  />
);

Não há mais suporte de lista horizontal

Anteriormente, os componentes de lista suportavam os modos de layout horizontal e vertical. Para simplificar a implementação e manutenção, e como o caso de uso mais comum são as listas verticais, removerei o suporte para layout="horizontal" .


Suporte RTL

Os componentes da grade continuarão a oferecer suporte a direction="RTL" , mas as listas não (uma vez que suportarão apenas layout vertical). Essa troca está sendo feita para permitir que as listas sejam menores e mais fáceis de manter.


onItemsRendered e onScroll alterações de retorno de chamada

Os componentes de lista e grade atualmente suportam onItemsRendered e onScroll props de retorno de chamada. Esses retornos de chamada são chamados durante a fase de confirmação (após a lista ou grade ter concluído a renderização). Isso pode ser útil porque é sempre seguro executar um efeito colateral (como registro de análise) em resposta a esses retornos de chamada, mas também tem uma desvantagem: qualquer atualização sincronizada de rolagem deve ser feita em uma segunda renderização ("em cascata") .

A versão 2 fará uma alteração no retorno de chamada onScroll para resolver isso. O retorno de chamada onScroll será chamado durante o ciclo de envio do evento para que qualquer atualização seja agrupada (pelo React) com a própria atualização da lista ou grade.

O retorno de chamada onItemsRendered será substituído por um onItemsDisplayed prop , embora continue a ser chamado durante o ciclo de confirmação. Essa alteração está sendo feita para permitir que o componente de lista otimize de forma mais agressiva o desempenho de renderização, pré-renderizando em prioridade inativa e fazer uso de APIs experimentais, como bloqueio de exibição .


Outras alterações / depreciações de adereços

Existem várias descontinuações pendentes (com avisos DEV) que serão removidas:

  • innerTagName e outerTagName para todos os componentes de lista e grade. (Use innerElementType e outerElementType vez disso.)
  • overscanCount , overscanColumnsCount e overscanRowsCount para o componente da grade. (Use overscanColumnCount e overscanRowCount vez disso.)
  • overscanCount será removido para os componentes da lista, em favor de uma abordagem dinâmica de overscan.
  • valores "horizontal" e "vertical" para direction . (Eles foram movidos para layout , mas serão totalmente removidos na versão 2.)
  • O itemData prop (e o data prop correspondente passado aos representantes de itens) será removido porque a mudança para uma API de prop de renderização não torna isso mais necessário.
  • O useIsScrolling prop (e o isScrolling prop correspondente passado aos representantes de itens) será removido porque as alterações na pré-renderização e no bloqueio de exibição tornariam isso mais caro de implementar.
  • Os parâmetros de alinhamento de rolagem serão ligeiramente alterados. O anteriormente denominado "auto" agora será denominado "mínimo". O novo valor padrão será "inteligente" (em vez de "automático").

Observe que alguns dos adereços obsoletos acima podem não ser relevantes devido às outras mudanças planejadas, mas estou listando-os aqui de qualquer maneira para fins de integridade.

👋 help wanted 💬 discussion

Comentários muito úteis

As listas horizontais são amplamente utilizadas em dispositivos móveis em nosso caso. Também os usamos para um carrossel com rolagem infinita. IMO deve ter algo no celular.

Todos 44 comentários

As listas horizontais são amplamente utilizadas em dispositivos móveis em nosso caso. Também os usamos para um carrossel com rolagem infinita. IMO deve ter algo no celular.

Obrigado por compartilhar um caso de uso @istarkov. Não é que eu não ache que existam _qualquer_ casos de uso válidos para janelas horizontais. Só acho que são muito menos comuns. (Mesmo no caso de carrosséis, muitos usam navegação de seta para a esquerda / direita que não requer janelas baseadas em eventos de "rolagem".) Acho que ainda pode ser o melhor caminho (para mim) abandonar o suporte para v2 para ajudar a compensar da complexidade que estou planejando introduzir com pré-renderização, dimensionamento dinâmico, etc.

Estou muito animado com essa abordagem mais enxuta que, com sorte, levará a um código mais simples, com mais desempenho e mais simples.

Excelente. Mas tenho poucas preocupações em descartar a lista de tamanho variável. Você está planejando substituir a lista de tamanho variável por DynamicList, mas o problema com a lista dinâmica é que você não pode rolar para o item, o que pode ser um recurso muito útil para alguns componentes e tal requisito pode surgir com o tempo, então você não pode prever se react-window atende às suas necessidades.
O segundo problema que vejo é o desempenho da lista dinâmica, se você pode fornecer o mesmo desempenho para a lista dinâmica e para a lista de tamanho variável, pode ser ok para descartá-la mesmo que você não suporte scrollToItem, mas se não, os desenvolvedores podem ficar bloqueados situações estranhas onde a lista dinâmica é lenta e não tem suporte para rolar para o item, a lista tem apenas a altura fixa dos itens.

Você está planejando substituir a lista de tamanho variável por DynamicList, mas o problema com a lista dinâmica é que você não pode rolar para o item

Não acho que seja uma limitação inerente, apenas uma da implementação atual. Tenho ideias de como poderia oferecer essa função. Se encontro tempo para resolver isso é outra questão: sorria:

O segundo problema que vejo é o desempenho da lista dinâmica, se você pode fornecer o mesmo desempenho para a lista dinâmica e para a lista de tamanho variável, pode ser ok para descartá-la mesmo que você não suporte scrollToItem, mas se não, os desenvolvedores podem ficar bloqueados situações estranhas onde a lista dinâmica é lenta e não tem suporte para rolar para o item, a lista tem apenas a altura fixa dos itens.

É difícil dizer se ele terá um bom desempenho. Parece que a lista dinâmica terá que trabalhar mais, então é provável que não funcione tão bem. Talvez a diferença seja significativa, talvez não. Quero ser capaz de oferecer suporte a algumas coisas que não faço no momento e acho que preciso reduzir o escopo para adicionar novos recursos. Se você está satisfeito com a lista de variáveis, não há razão para atualizar para a v2 (pelo menos em breve).

@bvaughn Isso parece documentação para mim!
Você tem trabalhado nisso desde o verão passado? ;-)

Em uma nota mais séria - acho que adereços de renderização fazem sentido neste contexto, embora eu não seja um fã.

Não, eu escrevi esta manhã 😝 Estou exausto.

Acho que os adereços de renderização fazem sentido neste contexto, embora eu não seja um fã.

Você pode explicar por que não é fã?

O suporte de lista / grade horizontal poderia fazer sentido como um recurso opcional como AutoSizer (react-virtualized-auto-sizer)?

Eu usei o react-virtualized e o react-window para listas horizontais e achei a API da react-window muito mais simples. Embora eu def entenda a necessidade da suspensão na esperança de uma API mais simples.

O suporte à rede ainda está planejado. Opte pelo suporte horizontal, não realmente. Não acho que isso faria sentido.

@bvaughn Eu geralmente gosto de render props e eles vão resolver os problemas que você delineou, mas eu acho que eles encorajam uma função inline que pode ou não conter um monte de lógica aninhada. 🤔 Qualquer falha aqui recai sobre o usuário. 🙂

você pode perceber grade de alvenaria?

@nikitapilgrim Não. Eu sugeriria apenas usar o componente Masonry de react-virtualized

https://github.com/bvaughn/react-virtualized/blob/master/docs/Masonry.md

obrigado, mas seu trabalho apenas com virtualizado de reação?

@nikitapilgrim Sim. 👍
O React-virtualizado oferece suporte a vários recursos, que o react-window não tem.

O escopo da janela de reação é drasticamente reduzido, para focar em tornar o pacote menor e mais rápido . 😉

Se você precisa de recursos de virtualização reativa, sugiro que continue com eles - ainda é uma ótima biblioteca!

Eu tropecei em react-window porque estava procurando uma solução para este problema de react-virtualized babel 7 . Estou usando os react-virtualized Masonry componentes, mas não posso mais depois de atualizar babel .

Este não é o lugar para relatar problemas com virtualizado de reação.

Concordo com @bvaughn. No entanto, você e @babangsund responderam a @nikitapilgrim acima que um componente Masonry não será introduzido em react-window e, em vez disso, usaremos react-virtualized . No entanto, se um usuário estiver no [email protected] e [email protected] mais recentes (como com create-react-app ), react-virtualized não funcionará necessariamente.

Acho que é uma informação útil para qualquer pessoa que esteja descendo pela mesma toca do coelho.
¯ \ _ (ツ) _ / ¯

Ei, eu quero usar a lista de tamanhos dinâmicos, onde posso baixar a versão 2 ou terei que usar o react virtualizar?
image

esta é a aparência da minha lista com a lista de tamanho variável

Este não é um problema de suporte genérico. Por favor, mantenha comentários sobre o tópico.

Feedback é apreciado

Estou usando react-window em um produto semelhante ao trello e aqui estão algumas idéias:

Renderizar adereços

Esta parece ser uma boa mudança devido à simplicidade e para evitar o lado negativo mencionado. Além disso, a api seria mais semelhante à FlatList do react-native. Lembro-me de ter lido a discussão em https://github.com/bvaughn/react-window/issues/85.

Menos componentes
Não há mais suporte de lista horizontal

Eu voto fortemente contra a remoção do suporte de horizontal e VariableSizeList . Como você pode imaginar, esses são os dois principais que utilizo. A sua implementação é realmente muito difícil de manter? Se não, espero que você possa reconsiderar e mantê-los.

Não tenho opiniões fortes em relação às outras mudanças. A remoção de overscanCount me preocupa um pouco, mas ainda não enfrentei casos de uso em que um valor personalizado fosse necessário, então provavelmente está tudo bem.

Ei @bvaughn! Obrigado por este pacote! Estou procurando incorporar a versão 2 em meu projeto no trabalho. Você tem uma estimativa de quando isso será lançado?

Obrigado por esta biblioteca e compartilhar seu plano para lançamentos futuros é muito útil para nos ajudar a mitigar o débito técnico.

Existe uma maneira "simples" de ter um comportamento de WindowScroller usando o react-window recente e posterior na versão 2?

Se não fosse possível, estaria fora do perímetro desta versão 2? ou isso poderia ser adicionado mais tarde?

Meu contexto é que meu layout inclui um rodapé, e usando uma abordagem moderna como DynamicSizeList introduziria uma segunda barra de rolagem (uma para a página e outra para a lista de produtos)

Ótimo pacote. Aguardo ansiosamente listas de altura dinâmica por padrão - no momento, eu escrevi um monte de lógica personalizada para passar alturas de linha renderizadas de volta para a lista pai. Espero que com esta nova versão eu possa remover essa lógica. Obrigado pelo seu trabalho nisso!

@ltkn @mrdanimal

Já existe uma maneira de usar o controle de janela:
https://github.com/bvaughn/react-window/issues/30#issuecomment -428868071

Como fazer Scroll infinito em ambas as direções, esquerda ou direita !!!

Se tivermos WindowScroller sem depender de react-virtualized , será ótimo. Porque o objetivo por trás de react-window tornou muito mais eficiente e menos código em comparação com react-virtualized Portanto, não quero usar WindowScroller de react-virtualized . Em vez disso, procure um pacote separado como react-virtualized-auto-sizer .

Desde já, obrigado.

@prabusamvel hm ..
Qual é a vantagem de um pacote separado?

Estou brincando com o novo DynamicSizeList. Muito legal! Acho que uma grande melhoria seria incluir 'ttb' e 'btt' (de cima para baixo, de baixo para cima) no tipo de direção. Atualmente não há uma maneira limpa de implementar uma lista que rola para cima, mas todas as outras direções são suportadas.

@toddmacintyre Não consigo encontrar esta versão 2.

@muhammedmagdi npm install react-window@next

Seria brilhante se a versão 2 pudesse suportar as estruturas DOM exigidas pela especificação aqui - https://www.w3.org/TR/wai-aria-1.1/#grid, pois # 217 ainda é um problema para nós. Pelo que eu posso dizer, sua proposta para a versão 2 agora não.

@mjurkowski @bvaughn yarn add react-window@next instala 1.6.0-alpha.1 . Além disso, ao tentar executar o exemplo de sandbox de lista dinâmica https://react-window-next.now.sh/#/examples/list/dynamic -size, ele lança Error importing GitHub repository: Could not find package.json

Que tal passar index na grade também - enquanto estiver fazendo isso? :)

Parte de nosso aplicativo requer uma grade com cabeçalhos de coluna de largura variável. Conseguimos isso usando uma lista de tamanho variável horizontal associada a uma grade e sincronizando a rolagem das duas.

Remover listas horizontais nos impedirá de criar essa IU (ou pelo menos teremos que reescrevê-la para usar 2 grades onde a grade do cabeçalho da coluna tem uma única linha.

O próximo produto parece incrível. Mas eu preciso de horizontal e vertical, então, para sua informação, criei o meu próprio: https://www.npmjs.com/package/react-infinite-grid-scroller. Usa layout de grade, ganchos de reação, IntersectionObserver e requestIdleCallback.

Feedback bem-vindo.

Tenho a sensação de que suportar elementos pegajosos seria um ótimo complemento para a janela de reação. É um caso de uso bastante comum e seria direto de implementar para listas e grades.

A API pode ter a seguinte aparência:

<Grid
    // First 2 columns are sticky
    stickyLeft={2}
    // Last column is not sticky (default value)
    stickyRight={0}
    // First and last rows are sticky
    stickyTop={1}
    stickyBottom={1}
/>

Os dois elementos principais para fazer a aderência funcionar são:

  1. apenas desmonte as células que são pegajosas se elas estiverem fora da janela no eixo, elas não são pegajosas
  2. use position: sticky vez de absolute , e use margin-x vez de left e top para o eixo que não é pegajoso

O custo de um recurso tão bom parece razoável:

  • A pegada é mínima
  • Sem grande impacto no desempenho (apenas renderizando algumas linhas / colunas extras)
  • O suporte do navegador é ótimo, e aqueles que não oferecem suporte a position: sticky apenas veem uma versão normal

Se você acha que este caso de uso é muito específico para ser suportado como está, um grande compromisso seria suportar apenas o ponto 1. Ser capaz de especificar se uma célula deve ser renderizada ou não permitiria implementar a aderência facilmente.

Eu ficaria feliz em ajudar, se necessário.

não oferece suporte à medição e atualização automática de seus tamanhos.

Eu sinto que este é um grande lado negativo. Para quase todas as grades que escrevi, preciso ter 3 ou 4 colunas de largura fixa (para um rótulo de status, alguns metadados, uma chamada para ação etc.) e 1 coluna de largura dinâmica que ocupa o resto do espaço disponível.

Compreendo que "não suporta" não significa necessariamente que isso não seja possível com a adição de código e componentes adicionais como o Autosizer - seria apenas bom ter esses casos de uso bem considerados e soluções documentadas para aqueles que precisam de um coluna dinâmica, mas não quer ir para a virtualização de reação por toda a bagagem que ela traz consigo.

seria muito bom ter esses casos de uso bem considerados e soluções documentadas para aqueles que precisam de uma coluna dinâmica

Totalmente compreendido - mas falando de maneira prática, isso exigiria muito esforço , e esta biblioteca foi um trabalho de amor (não um empreendimento pago). Infelizmente, nem tive tempo de terminar meus esforços de v2 no escopo inferior , muito menos algo mais agressivo. 😞

seria muito bom ter esses casos de uso bem considerados e soluções documentadas para aqueles que precisam de uma coluna dinâmica

Totalmente compreendido - mas falando de maneira prática, isso exigiria muito esforço , e esta biblioteca foi um trabalho de amor (não um empreendimento pago). Infelizmente, eu nem tive tempo de terminar meus esforços de _dimensionamento_ v2, muito menos algo mais agressivo. 😞

Sim. Entendi. Esperançosamente, esse tipo de esforço pode ser liderado pela comunidade.

Seria bom, mas na minha experiência, isso nunca acontece: sorria:

Não consegui usar WindowScroller com DynamicSizedList, provavelmente por causa da renderização just-in-time que faz scrollTo não funcionar muito bem. Isso será possível com a nova versão?

Aceitei o fato de não ter tempo nem energia para terminar esse esforço. Se alguém quiser intervir e terminar o ramo que comecei, gostaria de receber sua ajuda. (Consulte também a edição # 6 para obter detalhes sobre List e Grid devem ser implementados para oferecer suporte a medições just-in-time.)

Olá @bvaughn ,
Eu criei uma discussão no meu garfo com algumas notas aleatórias.
Avise-me se houver algo que não deveria estar na lista ou que não esteja correto. Vou completar a lista quando fizer progresso.

Parece coisa boa

Esta página foi útil?
0 / 5 - 0 avaliações