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

为何useEffect清理函数在应用启动时执行?query未变更

为什么useEffect的清理函数在应用启动时就执行了?

你遇到的是React**严格模式(Strict Mode)**在开发环境下的特殊行为——它会主动重复执行组件的挂载逻辑,包括调用useEffect,并且在第一次执行后立即触发清理函数,随后再次运行useEffect。这是React的调试机制,用来帮你排查未正确清理的副作用(比如未取消的网络请求、遗留的定时器),生产环境不会出现这个现象。

结合你的代码来看:
你的query初始值固定为"interstellar",没有变化,但在开发环境的Strict Mode下,React会按以下流程执行:

  • 第一次执行useEffect,发起网络请求
  • 立即调用清理函数(controller.abort()),中止第一次请求
  • 再次执行useEffect,重新发起请求

这就是你看到启动时清理函数执行的原因,并非你的代码逻辑错误,只是开发环境的调试行为。

你可以通过暂时移除根组件的<React.StrictMode>包裹来验证这一点,此时清理函数只会在组件卸载或者query变化时执行。

你的代码片段:

const [movies, setMovies] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState("");
const [query, setQuery] = useState("interstellar");

useEffect(() => {
    const controller = new AbortController();

    async function fetchMovies() {
      try {
        setError("");
        setIsLoading(true);
        const res = await fetch(
          `http://www.omdbapi.com/?apikey=${KEY}&s=${query}`,
          { signal: controller.signal }
        );
        if (!res.ok) throw new Error("Failed to fetch movies");
        const data = await res.json();
        if (data.Response === "False") throw new Error("No movies found");
        setMovies(data.Search);
      } catch (err) {
        console.error(err.message);
        if (err.name !== "AbortError") setError(err.message);
      } finally {
        setIsLoading(false);
      }
    }

    if (!query) {
      setMovies([]);
      setError("");
      return;
    }

    fetchMovies();

    return () => controller.abort();
  }, [query]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:22:12