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)
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 é
invariant violation: Portal is not support on SSR. For more detail, please refer https://github.com/facebook/react/issues/13097
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.
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 (
)
}
} `
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.