简体   繁体   English

服务器端渲染元素应在初始渲染时滚动到底部

[英]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.

相关问题 保持元素滚动到底部 - Keep an element scrolled to the bottom 服务器端 React Initial Render 导致重复的异步调用 - Server Side React Initial Render causes duplicated async calls React 中的每个页面都应该在服务器端呈现吗? - is every page in React should be Server-Side rendered? React - 初始渲染后渲染的项目没有更新。 当道具发生变化时,select 是否应该有不同的数据 - React - Rendered item is not updating after initial render. When props change, should select different data JSON对象vs窗口变量,用于使用reactjs传递服务器端呈现的初始状态 - JSON object vs window variable for passing server-side rendered initial state using reactjs 检测反应滚动到底部元素。 scrollTop - detect react scrolled to bottom element. scrollTop 如何确定您是否已滚动到元素的底部? - How to determine if you have scrolled to the bottom of an element? 您如何判断请求是否应呈现在服务器端? (ReactJS) - How can you tell if a request should render server side? (ReactJS) 错误:Hydration 失败,因为初始 UI 与使用 Link 元素时在服务器上呈现的内容不匹配 - Error: Hydration failed because the initial UI does not match what was rendered on the server when using Link element 是在客户端还是在服务器端渲染图像? - Are Images Rendered Client Side or Server Side?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM