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

使用useEffect预加载API数据无效,点击按钮仍耗时6秒求排查

问题分析与解决

你的代码逻辑上应该在组件挂载时通过useEffect预加载API数据,但点击按钮仍需等待,核心问题大概率是按钮点击时重复发起了API请求,而非直接复用预加载好的本地数据。

先确认预加载是否生效

打开浏览器控制台,组件加载时如果能看到hello和RUNNING HANDLER的打印,以及随机数输出,说明预加载已经执行,数据已经存在movies状态里了。如果没看到这些日志,检查组件是否有条件渲染逻辑导致useEffect未触发。

修复方案

方案1:按钮直接复用预加载数据

如果按钮的作用是展示数据,完全不需要再调用fetchMoviesHandler,只需要控制一个显示状态即可:

const [showMovies, setShowMovies] = useState(false);

// 按钮点击事件
const handleShowMovies = () => {
  setShowMovies(true);
};

// 渲染部分
{showMovies && !isLoading && (
  <div>
    {movies.map(movie => (
      <div key={movie.id}>
        <h3>{movie.title}</h3>
        <p>{movie.openingText}</p>
      </div>
    ))}
  </div>
)}

方案2:让请求函数优先用缓存数据

如果按钮必须保留触发请求的逻辑,修改fetchMoviesHandler,先判断本地是否已有数据,有则直接返回:

const fetchMoviesHandler = useCallback(async () => {
  // 优先用本地缓存的数据
  if (movies.length > 0) {
    console.log("使用预加载缓存数据");
    return;
  }

  const random = Math.random();
  console.log(random);
  console.log("RUNNING HANDLER");
  try {
    setError(null);
    setIsLoading(true);
    const response = await fetch(`https://swapi.dev/api/films`);
    if (!response.ok) {
      throw new Error("Something went wrong");
    }
    const data = await response.json();
    const transformedMovies = data.results.map((movieData) => {
      return {
        id: movieData.episode_id,
        title: movieData.title,
        openingText: movieData.opening_crawl,
        releaseDate: movieData.release_date,
      };
    });
    setMovies(transformedMovies);
    setIsLoading(false);
  } catch (error) {
    setError(error.message);
    setIsLoading(false);
    console.log(error);
  }
}, [movies]); // 依赖添加movies,确保状态更新时函数同步

额外优化:区分预加载和按钮触发的加载状态

预加载时的loading状态如果不想让用户感知,可以新增独立的状态变量:

const [isPreloading, setIsPreloading] = useState(true);

const fetchMoviesHandler = useCallback(async () => {
  try {
    const response = await fetch(`https://swapi.dev/api/films`);
    if (!response.ok) {
      throw new Error("Something went wrong");
    }
    const data = await response.json();
    const transformedMovies = data.results.map((movieData) => {
      return {
        id: movieData.episode_id,
        title: movieData.title,
        openingText: movieData.opening_crawl,
        releaseDate: movieData.release_date,
      };
    });
    setMovies(transformedMovies);
  } catch (error) {
    setError(error.message);
    console.log(error);
  } finally {
    setIsPreloading(false);
  }
}, []);

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

// 按钮点击仅在无缓存时显示loading
const handleButtonClick = () => {
  if (movies.length === 0) {
    setIsLoading(true);
    fetchMoviesHandler().then(() => setIsLoading(false));
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:37:38