React: autoFocus não funciona com SSR no React 16

Criado em 9 out. 2017  ·  12Comentários  ·  Fonte: facebook/react

<input autoFocus /> funciona no cliente, mas não quando hidratado.

Isso ocorre porque isso costumava ser implementado em JS como um caso especial, mas hydrateInstance não faz com que um efeito de confirmação seja agendado que possa chamar .focus() como finalizeChildren .

A questão aqui é: devemos nos incomodar mais em implementar isso em JS ou apenas emitir o atributo autofocus em SSR e deixar o navegador cuidar disso.

Server Rendering Bug

Comentários muito úteis

O motivo inicial para não emitir o atributo autofocus era que as implementações do navegador eram amplamente inconsistentes na forma como o tratavam (alguns não suportam, alguns focam apenas no carregamento da página, etc). Qual IMHO significa que qualquer pessoa que leva a sério o foco automático teve que aplicá-lo manualmente via JS de qualquer maneira. No entanto, eu me lembro vagamente de agora haver navegadores móveis que realmente não ouvem o foco JS, mas respeitam o foco automático até certo ponto.

É uma bagunça, mas há algum mérito em apenas emitir o atributo, e se você tem uma opinião forte sobre isso, então você se concentra manualmente. Você recebe todas as ferramentas.

Todos 12 comentários

Acho que devemos emitir autofoco como um atributo.

Parece que a principal desvantagem é que autofocus não é compatível com o navegador IE9, iOS Safari e Android . Existem outras desvantagens que estou perdendo? Quão difícil / mecânico seria adicionar autofoco via JS?

Se sempre fizermos isso em JS, é muito fácil, mas parece muito ruim para a semântica. Pode demorar um pouco para que todos os scripts sejam carregados antes que ele seja realmente focalizado. O usuário pode se concentrar em outras coisas enquanto isso e, de repente, ele se torna focado. Visto que com o Fibra podemos reidratar de forma assíncrona e também podemos querer fazer uma hidratação parcial, isso pode tornar isso ainda pior do que já é.

Podemos fazer as duas coisas, mas você tem artefatos estranhos onde pode ficar focado, você desliga e então fica focado novamente.

Potencialmente, só poderíamos fazer isso em JS se o normal falhar, mas não temos certeza de como detectá-lo e isso pode adicionar muito código.

Não tenho certeza de qual é a compensação certa aqui, dado o problema de suporte do navegador.

Pode demorar um pouco para que todos os scripts sejam carregados antes que ele seja realmente focalizado.

Acho que este é um caso muito forte para a emissão de um atributo. Parece que não podemos garantir a correção, mesmo se verificarmos document.activeElement , o usuário pode já estar em um fluxo ou ter rolado a página para baixo. Não queremos que a página pule ou que alguém comece a digitar em outra caixa de entrada no meio de um toque de tecla.

Desculpe se parte disso é uma repetição, mas esse seria o argumento que eu faria se alguém registrasse um problema sobre isso.

Atributo de emissão parece ser o caminho certo a seguir. Se eu quiser que o foco automático funcione em navegadores que não o suportam, parece mais lógico adicionar um script ao final do corpo:

    <script>!function(el){el&&el.focus()}(document.querySelector('[autofocus]'))</script>

O que eu acho que só causa problemas se a página HTML for muito grande. Eu acho que também poderia verificar o activeElement (se nenhum ou corpo, então foco), mas isso pode ser um exagero.

O motivo inicial para não emitir o atributo autofocus era que as implementações do navegador eram amplamente inconsistentes na forma como o tratavam (alguns não suportam, alguns focam apenas no carregamento da página, etc). Qual IMHO significa que qualquer pessoa que leva a sério o foco automático teve que aplicá-lo manualmente via JS de qualquer maneira. No entanto, eu me lembro vagamente de agora haver navegadores móveis que realmente não ouvem o foco JS, mas respeitam o foco automático até certo ponto.

É uma bagunça, mas há algum mérito em apenas emitir o atributo, e se você tem uma opinião forte sobre isso, então você se concentra manualmente. Você recebe todas as ferramentas.

Conversei com

Reagir 16

  • Emita-o em SSR HTML.
  • Certifique-se de não chamar JS polyfill para elementos hidratados.
  • Continue colocando-o na lista negra dos elementos criados pelo cliente e use JS polyfill para eles.

Reagir 17

  • Remova JS polyfill completamente.
  • Avisa se há mais de um elemento autoFocus adicionado durante um commit (já que é aqui que ocorrem as inconsistências do navegador).

Isso faz sentido?

Avisa se há mais de um elemento autoFocus adicionado durante um commit (já que é aqui que ocorrem as inconsistências do navegador).

Os navegadores, pelo menos não há muito tempo, também são inconsistentes em como interpretam o atributo autoFocus. Eu sei que, por exemplo, FF só o honraria no carregamento de página e ignoraria totalmente qualquer um que fosse inserido dinamicamente. Mas já faz muito tempo que não faço isso.

Mesmo assim, acho que a abordagem está correta.

Após alguma investigação básica, parece que a maioria dos navegadores modernos, exceto o Safari, não respeita autoFocus após o carregamento da página.

Provavelmente fazia sentido para documentos HTML, mas em aplicativos eu esperaria que autoFocus fosse respeitado por elementos inseridos dinamicamente, já que eles são basicamente "transições de página" tanto quanto o carregamento da primeira página em SPAs.

Portanto, provavelmente devemos manter o polyfill.

Isso fica mais estranho.

O Chrome respeita os elementos adicionados dinamicamente com autoFocus se não houver um antes. Até mesmo criar uma entrada com autoFocus , adicioná-la ao documento e removê-la no próximo tique é suficiente para desabilitar o foco automático de quaisquer elementos adicionados no futuro no Chrome.

O Firefox simplesmente não se importa com nenhum elemento adicionado dinamicamente com autoFocus .

E o Safari sempre os respeita.

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