You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件页面加载/卸载API调用异常排查请求

问题排查与修复:React页面加载API重复调用及卸载逻辑异常

问题描述

我希望通过React组件实现:特定页面加载时仅调用一次API,用户导航至其他页面(页面卸载时)再调用一次API。但编写的ActivityTracker组件出现两个问题:页面加载时API调用两次,未卸载页面就触发卸载API调用。

原代码

function ActivityTracker() {
  // Function to make the API call on page load
  const onPageLoad = async () => {
    try {
      const response = await fetch(
        'https://jsonplaceholder.typicode.com/todos/1'
      );
      const data = await response.json();
      // Handle the data as needed
    } catch (error) {
      console.error('Error on page load:', error);
    }
  };

  // Function to make the API call on page unload
  const onPageUnload = async () => {
    try {
      const response = await fetch(
        'https://jsonplaceholder.typicode.com/todos/1'
      );
      const data = await response.json();
      // Handle the data as needed
    } catch (error) {
      console.error('Error on page unload:', error);
    }
  };

  useEffect(() => {
    onPageLoad();
  }, []);

  return <div>Your page content goes here</div>;
}

export default ActivityTracker;

问题分析

  1. 页面加载API调用两次

    • 核心原因是React 18+的严格模式(StrictMode):开发环境下,StrictMode会对组件进行两次渲染,用于检测潜在的副作用问题,因此空依赖的useEffect会执行两次,导致API调用重复。
    • 额外排查点:检查父组件(如App.js)是否重复挂载了ActivityTracker组件。
  2. 未卸载就触发卸载API

    • 原代码未实现卸载时的API调用逻辑:没有在useEffect的清理函数中绑定onPageUnload。若出现提前触发的情况,大概率是组件被意外卸载/重建(比如父组件状态变化导致重渲染,组件被销毁后重新挂载)。

修复方案

修复后的完整代码

function ActivityTracker() {
  // 页面加载时的API调用
  const onPageLoad = async () => {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const data = await response.json();
      console.log('页面加载API返回数据:', data);
    } catch (error) {
      console.error('页面加载API调用失败:', error);
    }
  };

  // 页面卸载时的API调用
  const onPageUnload = async () => {
    try {
      // 关键:unload事件中需配置keepalive,避免请求被浏览器中断
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1', {
        keepalive: true
      });
      const data = await response.json();
      console.log('页面卸载API返回数据:', data);
    } catch (error) {
      console.error('页面卸载API调用失败:', error);
    }
  };

  useEffect(() => {
    // 页面加载时执行一次API调用
    onPageLoad();

    // 定义清理函数,组件卸载时自动执行
    return () => {
      onPageUnload();
    };
  }, []);

  return <div>页面内容</div>;
}

export default ActivityTracker;

关键修复说明

  • 解决加载时重复调用:

    • 开发环境下StrictMode的两次渲染是正常检测机制,生产环境不会出现。若需在开发环境临时避免,可移除根组件外的<StrictMode>标签(不推荐长期移除,建议保留以检测副作用)。
    • 确保ActivityTracker在父组件中仅被挂载一次。
  • 实现正确的卸载调用逻辑:

    • 在useEffect的返回值中定义清理函数,组件卸载时会自动执行该函数,触发onPageUnload。
    • 添加keepalive: true配置:页面卸载时(如关闭浏览器、导航跳转),浏览器可能中断未完成的请求,该配置可确保请求能成功发送至服务器。

内容的提问来源于stack exchange,提问作者Dhanesh Mane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:12:35