React: Aviso inesperado ao hidratar com portal e SSR

Criado em 15 abr. 2018  ·  24Comentários  ·  Fonte: facebook/react

Você quer solicitar um recurso ou relatar um bug ?

erro

Qual é o comportamento atual?

Dado o seguinte snippet (simplificado):

class HoverMenu extends React.Component {
  render() {
    if (typeof document === 'undefined') return null
    const root = document.getElementById('root')
    return ReactDOM.createPortal(<div>Hello World</div>, root)
  }
}

class Para extends React.Component {
  render() {
    return (
      <span>
        Some Text
        <HoverMenu />
      </span>
    )
  }
} 

onde div#root é um div válido que existe, o seguinte erro é mostrado ao hidratar após SSR:

Warning: Expected server HTML to contain a matching <div> in <span>

O aviso desaparece se eu atualizar a definição de HoverMenu para:

class HoverMenu extends React.Component {
  componentDidMount() {
    this.setState({ isActive: true })
  }
  render() {
    const { isActive} = this.state
    if (!isActive) return null
    const root = document.getElementById('root')
    return ReactDOM.createPortal(<div>Hello World</div>, root)
  }
}

Eu preferiria não fazer isso por causa da renderização dupla causada por setState em componentDidMount .

Não entendo muito bem o que esse erro está me dizendo. Nenhum <div /> é renderizado do lado do servidor em nenhum dos casos. O erro é particularmente confuso, já que HoverMenu DOM div nem mesmo é processado dentro de um DOM span . (Eu me pergunto se isso está acontecendo porque HoverMenu está aninhado dentro de um React span .)

Qual é o comportamento esperado?

Nenhum erro é lançado. Ou, pelo menos, que a mensagem de erro seja mais clara.

Quais versões do React e quais navegadores / sistemas operacionais são afetados por esse problema?

Chrome 65
React 16.2
(SSR até Next 5.1)

medium Bug good first issue

Comentários muito úteis

Embora os portais de hidratação não sejam suportados (https://github.com/facebook/react/issues/13097), a mensagem em si não faz sentido. Precisamos investigar e consertar.

Todos 24 comentários

Eu tenho um problema semelhante, que também pode ser resolvido pela renderização novamente no cliente por meio de setState.
No meu caso, tento renderizar um modal dentro de um portal. O componente Modal retorna null quando renderizado no servidor e cria um portal no cliente. No entanto, o DOM fica confuso após a hidratação.

Por exemplo, se eu usar assim dentro do meu componente principal:

<Modal>
This is a test
</Modal>

<div className="some-div-after-the-modal">
</div>

Em vez de obter isso após a hidratação:

<!-- Inside the portal container -->
<div class="modal-wrapper">
    <div class="modal-content">This is a test</div>
</div>

<!-- In the main component -->
<div class="some-div-after-the-modal">
</div>

Eu entendi isso:

<!-- Inside the portal container -->
<div class="some-div-after-the-modal">
    <div class="modal-content">This is a test</div>
</div>

<!-- In the main component -->
<div class="some-div-after-the-modal">
</div>

E o aviso é o mesmo ( Expected server HTML to contain a matching <div> in <div> ). Eu uso o React 16.3 com um método SSR personalizado.

Não tenho certeza se esse é o comportamento pretendido.

Embora os portais de hidratação não sejam suportados (https://github.com/facebook/react/issues/13097), a mensagem em si não faz sentido. Precisamos investigar e consertar.

@gaearon O objetivo da correção é

  • [] Detecta que o Portal está sendo usado em hydrate () e então lança uma mensagem de erro mais adequada pelo invariante.
    por exemplo, invariant violation: Portal is not support on SSR. For more detail, please refer https://github.com/facebook/react/issues/13097
  • [] Adicionar Teste

    • [] Se o Portal for usado com o hidrato (), deve lançar a mensagem de erro acima

direito?
Estou disposto se não for urgente.

Estou planejando o rascunho do documento SSR para o repositório do site, então preciso estar familiarizado com o mecanismo de hidratação.
Acho que esta investigação será útil para o meu plano.
https://github.com/facebook/react/pull/13379

Por que os Portals não são compatíveis com SSR, mesmo para renderizar "nada"?

Não parece que a renderização de nada é melhor - não vejo o que torna o conteúdo do portal diferente, pois não consideramos que valha a pena renderizar pelo servidor.

Provavelmente vamos voltar a isso junto com a reformulação do renderizador de servidor para suspense.

Os portais são conceitualmente componentes exclusivos do cliente; usado para coisas como modais que geralmente não queremos renderizar no servidor - eles também aceitam um elemento dom, o que renderToString não faz porque não há dom. Não vejo como haja algo significativo a ser feito com eles no servidor - também não vejo nada valioso em jogar.

usado para coisas como modais

Esse é um caso de uso, mas também existem outros, como barras laterais e semelhantes, que não são necessariamente exclusivos do cliente.

eles também têm um elemento dom

Certo - no design atual. Isso pode mudar. https://github.com/facebook/react/pull/8386#issuecomment -262375265

Eu também não vejo nada valioso em jogar.

O valor de jogar é reconhecer explicitamente que o portal não funcionará. Você pode contornar isso facilmente com {domNode && ReactDOM.createPortal(stuff, domNode)} ou similar. Porque você já teve que fazer algum tipo de verificação para determinar se pode obter o nó DOM - então, neste ponto, você deve ter dados suficientes para optar por não emitir o portal.

Eu gostaria de corrigir isso como meu "bom primeiro problema"

+1

Posso resolver esse problema?

Certo. Eu acho que você pode. Então, quão longe você foi? Na verdade, estou pensando em pegar também.

  • 2

Oi pessoal, alguma ideia de como posso encontrar o arquivo onde está o problema, posso pegá-lo por favor alguma ajuda.

Ei, aqui está a solicitação de pull parcial para esse problema
https://github.com/facebook/react/pull/15473

Alguém ainda está nisso? Eu adoraria assumir.

Qual é a situação disso? Como posso reproduzi-lo?

Isso ainda é um problema?

Também não obtive uma resposta sobre este assunto.

Acredito que o status desse problema ainda está em aberto.

Posso resolver esse problema?

Olá, alguém está trabalhando neste problema? Se não, eu gostaria de aceitar.

se ninguém está trabalhando nisso, eu posso

Isso ainda é um problema? Parece que foram feitas tentativas de corrigi-lo, mas o problema subjacente é que algumas pessoas realmente querem que os portais funcionem na renderização do lado do servidor. Se for esse o caso, este problema pode ser encerrado?

Adicionar um elemento div deve funcionar bem

`class Para extends React.Component {
render () {
Retorna (

Algum texto
)

}
} `

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