MST

星途 面试题库

面试题:React 服务端渲染中如何利用生命周期函数优化数据获取

假设你正在开发一个使用 React 进行服务端渲染的应用,其中部分组件需要从 API 获取数据。请详细描述如何利用 React 生命周期函数,特别是在服务端渲染场景下,优化数据获取过程,以提高性能和用户体验,包括但不限于何时发起请求、如何处理数据缓存等。
14.2万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. 生命周期函数选择

在 React 服务端渲染(SSR)场景下,常用 componentDidMount 在客户端发起数据请求。但由于 SSR 特性,为避免服务端和客户端数据不一致,还会用到 getInitialProps(在 Next.js 等框架中)或 static getDerivedStateFromProps

2. 何时发起请求

  • 服务端
    • 使用 getInitialProps(如 Next.js 框架),这个函数在组件实例化之前在服务端和客户端都会调用。在这里发起 API 请求,可以保证服务端渲染时就获取到数据并渲染到页面,减少首屏加载时间。例如:
import React from'react';
import axios from 'axios';

class MyComponent extends React.Component {
  static async getInitialProps() {
    const response = await axios.get('/api/data');
    return { data: response.data };
  }

  constructor(props) {
    super(props);
  }

  render() {
    return <div>{this.props.data}</div>;
  }
}

export default MyComponent;
  • 客户端
    • componentDidMount 中发起请求。当组件在客户端挂载完成后,再次发起请求以确保数据最新,同时处理缓存逻辑。例如:
import React from'react';
import axios from 'axios';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
  }

  async componentDidMount() {
    const response = await axios.get('/api/data');
    this.setState({ data: response.data });
  }

  render() {
    return <div>{this.state.data}</div>;
  }
}

export default MyComponent;

3. 处理数据缓存

  • 内存缓存
    • 在客户端,可以在全局作用域中设置一个缓存对象。每次发起请求前,先检查缓存中是否有数据。如果有,则直接使用缓存数据,不再发起请求。例如:
const dataCache = {};

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: dataCache['/api/data'] || null };
  }

  async componentDidMount() {
    if (!this.state.data) {
      const response = await axios.get('/api/data');
      this.setState({ data: response.data });
      dataCache['/api/data'] = response.data;
    }
  }

  render() {
    return <div>{this.state.data}</div>;
  }
}

export default MyComponent;
  • 本地存储缓存
    • 对于需要长期保存的数据,可以使用 localStorage。在每次获取数据后,将数据存储到 localStorage 中。下次加载组件时,先从 localStorage 读取数据。例如:
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    const cachedData = localStorage.getItem('/api/data');
    this.state = { data: cachedData? JSON.parse(cachedData) : null };
  }

  async componentDidMount() {
    if (!this.state.data) {
      const response = await axios.get('/api/data');
      this.setState({ data: response.data });
      localStorage.setItem('/api/data', JSON.stringify(response.data));
    }
  }

  render() {
    return <div>{this.state.data}</div>;
  }
}

export default MyComponent;

4. 性能优化

  • 批量请求:如果多个组件需要从同一 API 或相关 API 获取数据,可以将这些请求合并成一个请求,减少网络请求次数。
  • 错误处理:在请求过程中,要妥善处理错误。在服务端渲染时,如果请求失败,可以返回一个友好的错误提示页面,在客户端可以进行重试等操作,提升用户体验。例如:
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null, error: null };
  }

  async componentDidMount() {
    try {
      const response = await axios.get('/api/data');
      this.setState({ data: response.data });
    } catch (error) {
      this.setState({ error: '数据获取失败,请稍后重试' });
    }
  }

  render() {
    if (this.state.error) {
      return <div>{this.state.error}</div>;
    }
    return <div>{this.state.data}</div>;
  }
}

export default MyComponent;