MST

星途 面试题库

面试题:React中getSnapshotBeforeUpdate与性能优化及SSR的结合应用

在一个服务器端渲染(SSR)的React应用中,存在一个长列表组件,需要对列表滚动位置进行精准恢复,并且要考虑到性能优化,避免不必要的重渲染。请详细说明如何在这种复杂场景下,利用getSnapshotBeforeUpdate方法与SSR技术结合来达到目标,包括整体架构设计、数据存储与传输,以及关键代码逻辑。
30.9万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

整体架构设计

  1. 组件设计:将长列表组件设计为一个独立的React组件,该组件负责管理自身的滚动位置。同时,为了避免不必要的重渲染,可使用React.memo或shouldComponentUpdate对组件进行优化。
  2. SSR 集成:在服务器端渲染过程中,确保组件的初始状态(包括滚动位置)能够正确传递到客户端。这意味着服务器需要在渲染时收集并传递相关数据。

数据存储与传输

  1. 存储:在客户端,滚动位置可以存储在组件的state中。为了在SSR场景下能够恢复滚动位置,需要将滚动位置信息作为props从服务器传递到客户端。在服务器端,可以将滚动位置信息存储在某个数据结构中(例如在渲染上下文对象中)。
  2. 传输:通过在服务器端渲染时,将滚动位置数据嵌入到HTML中(例如作为自定义属性或JSON数据块),在客户端Hydration过程中,React可以读取这些数据并恢复组件的状态。

关键代码逻辑

  1. 服务器端渲染
import React from 'react';
import ReactDOMServer from'react-dom/server';
import MyListComponent from './MyListComponent';

// 假设这里有获取滚动位置的逻辑,例如从数据库或缓存中读取
const scrollPosition = getScrollPositionSomehow(); 

const html = ReactDOMServer.renderToString(
  <MyListComponent initialScrollPosition={scrollPosition} />
);

// 将html发送到客户端
  1. 客户端组件
import React, { useState, useEffect } from'react';

const MyListComponent = ({ initialScrollPosition }) => {
  const [scrollPosition, setScrollPosition] = useState(initialScrollPosition || 0);

  const handleScroll = (e) => {
    setScrollPosition(e.target.scrollTop);
  };

  useEffect(() => {
    const listElement = document.getElementById('my-list');
    if (listElement) {
      listElement.scrollTop = scrollPosition;
    }
  }, [scrollPosition]);

  const getSnapshotBeforeUpdate = (prevProps, prevState) => {
    const listElement = document.getElementById('my-list');
    return listElement? listElement.scrollTop : null;
  };

  const componentDidUpdate = (prevProps, prevState, snapshot) => {
    if (snapshot!== null) {
      const listElement = document.getElementById('my-list');
      if (listElement) {
        listElement.scrollTop = snapshot;
      }
    }
  };

  return (
    <div id="my-list" onScroll={handleScroll}>
      {/* 长列表内容 */}
    </div>
  );
};

export default MyListComponent;

在上述代码中:

  • initialScrollPosition作为props从服务器传递到客户端,用于初始化滚动位置。
  • useState管理滚动位置的状态。
  • handleScroll更新滚动位置状态。
  • useEffect在组件挂载和滚动位置更新时,设置实际的滚动位置。
  • getSnapshotBeforeUpdate方法在更新前捕获当前滚动位置。
  • componentDidUpdate方法在更新后恢复滚动位置,确保滚动位置精准恢复。同时,通过React.memo或shouldComponentUpdate对组件进行包裹,可进一步优化性能,避免不必要的重渲染。