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

避免组件重渲染后重复发起数据请求

解决组件卸载重挂载导致重复API请求的问题

你当前的问题根源在于:Parent组件用{toggle && <Child />}做条件渲染,当toggle从true切到false时,Child会被卸载;再切回true时,Child重新挂载,所以Child里的useEffect(空依赖数组)会再次执行,导致重复触发请求。

下面是几种可行的解决思路:

思路1:把请求逻辑提到父组件

将API请求放在Parent组件中,拿到数据后通过props传递给Child。这样无论Child是否挂载,数据都保存在Parent的状态里,只会发起一次请求。

修改后的代码:

import { useEffect, useState } from 'react';

function Child({ data }) {
  return <div>{data}</div>;
}

export default function Parent() {
  const [toggle, setToggle] = useState(false);
  const [data, setData] = useState("");

  // 在父组件中发起请求,仅执行一次
  useEffect(() => {
    console.log("fetching some data from server");
    setData(`this number should not change: ${Math.random().toString()}`);
  }, []);

  const onToggle = () => {
    setToggle(!toggle);
  };

  return (
    <>
      <button onClick={onToggle}>Toggle</button>
      {toggle && <Child data={data} />}
    </>
  );
}

思路2:不让Child被卸载,用CSS控制显示隐藏

不通过条件渲染移除Child组件,而是用CSS的display属性控制显隐,这样Child始终保持挂载状态,useEffect只会执行一次。

修改后的代码:

import { useEffect, useState } from 'react';

function Child() {
  const [data, setData] = useState("");

  useEffect(() => {
    console.log("fetching some data from server");
    setData(`this number should not change: ${Math.random().toString()}`);
  }, []);

  return <div>{data}</div>;
}

export default function Parent() {
  const [toggle, setToggle] = useState(false);
  const onToggle = () => {
    setToggle(!toggle);
  };

  return (
    <>
      <button onClick={onToggle}>Toggle</button>
      {/* 用CSS控制显隐,Child始终处于挂载状态 */}
      <Child style={{ display: toggle ? "block" : "none" }} />
    </>
  );
}

思路3:用全局状态存储数据(以Context为例)

如果多个组件需要复用这份数据,或者组件层级较深,可以将数据放到全局状态中,请求一次后全项目复用。这里用React Context做示例:

import { createContext, useContext, useEffect, useState } from 'react';

// 创建数据Context
const DataContext = createContext();

// 封装Provider组件统一管理数据
function DataProvider({ children }) {
  const [data, setData] = useState("");

  useEffect(() => {
    console.log("fetching some data from server");
    setData(`this number should not change: ${Math.random().toString()}`);
  }, []);

  return (
    <DataContext.Provider value={data}>
      {children}
    </DataContext.Provider>
  );
}

function Child() {
  // 从Context中获取数据
  const data = useContext(DataContext);
  return <div>{data}</div>;
}

export default function Parent() {
  const [toggle, setToggle] = useState(false);
  const onToggle = () => {
    setToggle(!toggle);
  };

  return (
    <DataProvider>
      <button onClick={onToggle}>Toggle</button>
      {toggle && <Child />}
    </DataProvider>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 11:32:53