[英]Server side rendered element should be scrolled to bottom on initial render
I'm building a React server side rendered application (Next.js) and have a scrollable <div>
that I want to be scrolled to the bottom on initial load of the page before React has hydrated the component.我正在构建一个 React 服务器端呈现的应用程序 (Next.js) 并有一个可滚动的
<div>
,我希望在 React 为组件补充水分之前在页面初始加载时将其滚动到底部。
That means a useLayoutEffect()
hook like the following is not sufficient because there will be a brief flash of the element scrolled to the top before React mounts and runs this hook.这意味着像下面这样的
useLayoutEffect()
钩子是不够的,因为在 React 安装和运行这个钩子之前,会有一个简短的 flash 元素滚动到顶部。
useLayoutEffect(() => {
const element = ref.current;
element.scrollTop = element.scrollHeight - element.clientHeight;
});
The approach that I think will work to prevent this is adding a <script>
tag in the server side rendered page.我认为可以防止这种情况发生的方法是在服务器端呈现的页面中添加一个
<script>
标记。 For example:例如:
function MyComponent() {
return (
<>
<div style={{overflowY: "scroll"}}>
...
</div>
<script>
var element = document.currentScript.previousElementSibling;
element.scrollTop = element.scrollHeight - element.clientHeight;
</script>
</>
);
}
However, I've found that when the <script>
executes the clientHeight
of the <div>
element is 0.但是,我发现当
<script>
执行时<div>
元素的clientHeight
为 0。
Presumably, I need to wait for the browser to finish loading the DOM so I added a DOMContentLoaded
listener:据推测,我需要等待浏览器完成加载 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>
</>
);
}
However, with this approach it appears the browser still does a paint with scrollTop
set to 0 and then processes the DOMContentLoaded
event handler.但是,使用这种方法,浏览器似乎仍然在
scrollTop
设置为 0 的情况下进行绘制,然后处理DOMContentLoaded
事件处理程序。
How can I write a <script>
here that executes the “scroll to bottom” behavior after DOM properties like element.clientHeight
have loaded but before the first browser paint so the user doesn't see a flash of the wrong scroll position.如何在此处编写
<script>
以在element.clientHeight
等 DOM 属性加载后但在第一次浏览器绘制之前执行“滚动到底部”行为,以便用户看不到错误滚动 position 的 flash。
Is there a better approach than this?还有比这更好的方法吗?
This version actually works in production.这个版本实际上在生产中工作。 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>
. 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>
.
So in production element.clientHeight
will be correct (since the CSS was loaded in the <head>
) but in development element.clientHeight
will be 0 (since the CSS will be loaded at the end of <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.