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

React Hook返回函数未调用却自动执行问题求助

问题

尝试创建一个返回可调用函数的React Hook,Hook内部创建该函数,最小复现代码如下:

// fetch.js
import { useEffect, useState} from "react";

export const useFetch = () => {
  
  const [fn, setFn] = useState(null);

  useEffect(() => {
    const fn_ = () => console.log("test")
    setFn(fn_)
  }, []);

  return fn;
}
// App.js
import { useFetch } from './fetch';

function App() {
  const fn = useFetch()
  
  return (
    <div className="App">
      hello
    </div>
  );
}

已禁用Strict模式:

// index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <App />
);

即使未调用fn(),控制台却输出了"test",函数被自动执行了。

原因

React的useState更新函数有特殊逻辑:当你向setState传递一个函数时,React会将这个函数视为状态更新器,它会立即执行该函数,并把函数的返回值作为新的状态值。

你这里的setFn(fn_)中,fn_是一个函数,所以React直接执行了它,导致console.log("test")被触发,而不是把fn_本身存在状态里。

解决方法

要将函数本身作为状态值存储,有两种常见方式:

方式一:用对象包裹函数

把函数放到对象中,这样传递给setFn的是对象而非函数,就不会被当作更新器执行:

useEffect(() => {
  const fn_ = () => console.log("test")
  setFn({ call: fn_ })
}, []);

// 调用时使用
// fn?.call()

方式二:传递返回目标函数的更新器

给setFn传递一个箭头函数,让它返回你要存储的函数,这样React会执行这个外层箭头函数,并把返回的目标函数作为状态值:

useEffect(() => {
  const fn_ = () => console.log("test")
  setFn(() => fn_)
}, []);

// 调用时直接使用
// fn?.()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:57:47