MST

星途 面试题库

面试题:React组件销毁阶段的关键生命周期方法及作用

在React组件销毁阶段,有哪些重要的生命周期方法?请阐述它们各自的作用以及在实际应用场景中可能会处理哪些操作。
23.9万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. componentWillUnmount

  • 作用:在组件即将从 DOM 中移除时调用,用于执行一些清理操作,比如取消网络请求、清除定时器、解绑事件监听器等,防止内存泄漏。
  • 实际应用场景操作
    • 取消网络请求:如果组件发起了 AJAX 请求,在组件销毁时使用 AbortController 取消未完成的请求。例如:
import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.controller = new AbortController();
  }

  componentDidMount() {
    fetch('/api/data', { signal: this.controller.signal })
      .then(response => response.json())
      .then(data => console.log(data));
  }

  componentWillUnmount() {
    this.controller.abort();
  }

  render() {
    return <div>My Component</div>;
  }
}

export default MyComponent;
- **清除定时器**:若组件内部使用了 `setInterval` 或 `setTimeout`,在组件销毁时清除定时器。如:
import React, { Component } from 'react';

class TimerComponent extends Component {
  constructor(props) {
    super(props);
    this.timer = null;
  }

  componentDidMount() {
    this.timer = setInterval(() => {
      console.log('Timer is running');
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

  render() {
    return <div>Timer Component</div>;
  }
}

export default TimerComponent;
- **解绑事件监听器**:如果在 `componentDidMount` 中为 `window`、`document` 等添加了事件监听器,在组件销毁时需要解绑。例如:
import React, { Component } from 'react';

class EventComponent extends Component {
  handleScroll = () => {
    console.log('Window scrolled');
  }

  componentDidMount() {
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll);
  }

  render() {
    return <div>Event Component</div>;
  }
}

export default EventComponent;

2. 从 React v17 开始,getSnapshotBeforeUpdate 与组件销毁的关联(间接相关)

  • 作用getSnapshotBeforeUpdate 在最近一次渲染输出(提交到 DOM 节点)之前调用。它返回的任何值将作为参数传递给 componentDidUpdate。虽然不是直接在组件销毁阶段调用,但它返回的值可能会影响到组件销毁时的清理逻辑。
  • 实际应用场景操作
    • 保存滚动位置:在列表组件更新时,记录更新前的滚动位置,以便在更新后恢复。假设列表组件可能在数据更新时重新渲染,导致滚动位置丢失。
import React, { Component } from 'react';

class ScrollableList extends Component {
  listRef = React.createRef();

  getSnapshotBeforeUpdate(prevProps, prevState) {
    if (prevProps.data.length!== this.props.data.length) {
      return this.listRef.current.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    if (snapshot!== null) {
      this.listRef.current.scrollTop = snapshot;
    }
  }

  componentWillUnmount() {
    // 在这里可以利用之前保存的滚动位置相关信息做一些清理或记录,
    // 例如记录用户最后浏览的位置到本地存储等操作
    const scrollTop = this.listRef.current.scrollTop;
    localStorage.setItem('lastScrollPosition', scrollTop);
  }

  render() {
    return (
      <div ref={this.listRef}>
        {this.props.data.map((item, index) => (
          <div key={index}>{item}</div>
        ))}
      </div>
    );
  }
}

export default ScrollableList;