[英]Server side rendered element should be scrolled to bottom on initial render
我正在构建一个 React 服务器端呈现的应用程序 (Next.js) 并有一个可滚动的<div>
,我希望在 React 为组件补充水分之前在页面初始加载时将其滚动到底部。
这意味着像下面这样的useLayoutEffect()
钩子是不够的,因为在 React 安装和运行这个钩子之前,会有一个简短的 flash 元素滚动到顶部。
useLayoutEffect(() => {
const element = ref.current;
element.scrollTop = element.scrollHeight - element.clientHeight;
});
我认为可以防止这种情况发生的方法是在服务器端呈现的页面中添加一个<script>
标记。 例如:
function MyComponent() {
return (
<>
<div style={{overflowY: "scroll"}}>
...
</div>
<script>
var element = document.currentScript.previousElementSibling;
element.scrollTop = element.scrollHeight - element.clientHeight;
</script>
</>
);
}
但是,我发现当<script>
执行时<div>
元素的clientHeight
为 0。
据推测,我需要等待浏览器完成加载 DOM,所以我添加了一个DOMContentLoaded
侦听器:
function MyComponent() {
return (
<>
<div style={{overflowY: "scroll"}}>
...
</div>
<script>
var element = document.currentScript.previousElementSibling;
document.addEventListener("DOMContentLoaded", function() {
element.scrollTop = element.scrollHeight - element.clientHeight;
});
</script>
</>
);
}
但是,使用这种方法,浏览器似乎仍然在scrollTop
设置为 0 的情况下进行绘制,然后处理DOMContentLoaded
事件处理程序。
如何在此处编写<script>
以在element.clientHeight
等 DOM 属性加载后但在第一次浏览器绘制之前执行“滚动到底部”行为,以便用户看不到错误滚动 position 的 flash。
还有比这更好的方法吗?
这个版本实际上在生产中工作。 It doesn't work in development because Next.js use's Webpack's style-loader
in development which means styles don't load until the JavaScript code has loaded and the JavaScript code is loaded at the end of the document <body>
.
所以在生产中element.clientHeight
将是正确的(因为 CSS 已加载到<head>
中)但在开发中element.clientHeight
将为0(因为 CSS 将在<body>
的末尾加载)。
function MyComponent() {
return (
<>
<div style={{overflowY: "scroll"}}>
...
</div>
<script>
var element = document.currentScript.previousElementSibling;
element.scrollTop = element.scrollHeight - element.clientHeight;
</script>
</>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.