javascript - React 正在渲染一个组件的一部分和另一个组件的一部分
问题描述
我正在构建的 Gatsby 网站中发生了一些非常奇怪的事情。我觉得这可能是一个我不知道的奇怪的 React 错误。太奇怪了,我可能很难描述它,但这里有:
我想将我的联系人页面上的不同页脚组件呈现给我网站的其余部分。组件相似但不相同。
我正在使用这样的代码:
{
!isContact ? // this is a useState state
<Footer /> :
<FooterContact />
}
错误是,有时当isContact
为真时,呈现的 html 由前几行Footer
组件组成,然后是我的组件的其余FooterContact
部分。即我得到:
<footer> // this is from the Footer component
<div class="inner"> // this is from the Footer component
<h1>Contact footer</h1> // this is from the FooterContact component
<p>Lorem Ipsum</p> // this is from the FooterContact component
</div>
</footer>
发生这种情况的条件是:
- 它只发生在实时服务器上。
- 只有当我“刷新”联系页面时才会发生这种情况。如果我通过另一个页面的链接前往那里,则该
FooterContact
组件呈现良好。
有没有人经历过这样的事情?
关于我可以尝试调试的任何建议?在过去的几个小时里,我一直在尝试一些东西,但我觉得我离弄清楚发生了什么更近了。
谢谢
解决方案
当服务器端呈现的 HTML 和客户端呈现的初始影子 DOM 之间存在差异时,就会发生这种情况。这会在 React 尝试将组件渲染的 DOM 输出与实时 HTML DOM 对齐的水合过程中导致问题。
根据取决于环境或渲染上下文的表达式,查找您正在有条件地渲染的代码区域。具体来说,您正在寻找任何可能导致在初始渲染期间呈现不同条件分支的表达式。
例如,这是一个问题:
const ExampleOfProblematicCode = () => {
const isClientSide = typeof window !== "undefined"
return isClientSide ? <div>Hello!</div> : null
}
相反,等到useEffect
钩子有机会执行并更改状态以提示重新渲染,然后再更改输出客户端:
const ExampleOfGoodPractice = () => {
const [isLoaded, setIsLoaded] = useState(false)
useEffect(() => { setIsLoaded(true) }, [])
return isLoaded ? <div>Hello!</div> : null
}
这将在初始渲染期间渲染相同的输出,之后 React 将运行导致生成并渲染备用条件分支的useEffect
钩子。isLoaded
true
编辑:澄清一下,当存在水合不匹配时,这种行为正是预期的:
发生这种情况的条件是:
- 它只发生在实时服务器上。
- 只有当我“刷新”联系页面时才会发生这种情况。如果我通过另一个页面的链接前往那里,FooterContact 组件会呈现良好。
这是因为初始加载是唯一包含预渲染 HTML 的加载。之后,React 水合物和 Gatsby 通过加载所需的 webpack 块和 page-data.json 文件来处理客户端导航,以在客户端呈现后续页面。
推荐阅读
- php - CORS HTTP 到 HTTPS
- python - 通过 shell 脚本运行 python 代码时无法读取环境变量
- javascript - 如何在 redux-form 中为 Field 设置“min”和“max”值
- python - 如何使用密码压缩类似文件的对象,然后在 Python 中将其上传到 s3?
- c# - 通过 WebApi 下载文件返回 JSON
- stm32 - 使用 HAL_SPI_Receive 接收错误的数据
- query-performance - 不相关的查询不应该在 not in 语句中只执行一次吗?
- jpa - JPA规范使用Entitry的minversion
- ruby-on-rails - 如何为 Rails + Rspec + Capybara & Selenium Webdrivers 为多域应用程序设置 Github CI?
- reactjs - 无法在 goormIDE 中启动 npm