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

如何用useCallback替代useEffect,避免按钮点击前触发多Fetch请求?

解决方案:避免页面加载时触发后续API请求

核心问题在于你原本的useEffect会在组件挂载(inputName初始为空字符串)时触发一次请求,同时setState的异步特性导致你尝试的useCallback方案无法获取到最新的inputName值。下面是两种直接有效的解决方式:

方案一:直接传递请求结果(推荐)

跳过状态依赖,在第一个请求完成后直接将返回的名称传递给后续请求,完全避免状态异步带来的问题,同时确保只有按钮点击后才会执行所有请求:

const [inputName, setInputName] = useState('');
const [inputStory, setInputStory] = useState('');
const [inputDes, setInputDes] = useState('');

const getOpenAIResponse = async () => {
  try {
    // 第一个请求获取名称
    const nameResponse = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: "Create a unique 1-5 word name.",
      max_tokens: 256,
    });
    const newName = nameResponse.data.choices[0].text.trim();
    setInputName(newName);

    // 直接用获取到的newName调用后续请求,无需等待状态更新
    await getStory(newName);
    await getDescription(newName);
  } catch (err) {
    console.error('请求出错:', err);
  }
};

// 改写为接收参数的函数,不再依赖inputName状态
const getStory = async (name) => {
  const response = await openai.createCompletion({
    model: "text-davinci-003",
    prompt: `Create a story about ${name}.`,
    max_tokens: 256,
  });
  setInputStory(response.data.choices[0].text);
};

const getDescription = async (name) => {
  const response = await openai.createCompletion({
    model: "text-davinci-003",
    prompt: `Create a description for ${name}.`,
    max_tokens: 256,
  });
  setInputDes(response.data.choices[0].text);
};

// 移除原有的useEffect,页面加载时不会触发任何请求

方案二:优化useEffect触发条件

如果一定要依赖状态,可以给useEffect增加判断逻辑,仅当inputName不为空时才执行后续请求,避免组件挂载时的无效请求:

const [inputName, setInputName] = useState('');
const [inputStory, setInputStory] = useState('');
const [inputDes, setInputDes] = useState('');

const getOpenAIResponse = async () => {
  try {
    const response = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: "Create a unique 1-5 word name.",
      max_tokens: 256,
    });
    setInputName(response.data.choices[0].text.trim());
  } catch (err) {
    console.error('请求出错:', err);
  }
};

const getStory = async () => {
  const response = await openai.createCompletion({
    model: "text-davinci-003",
    prompt: `Create a story about ${inputName}.`,
    max_tokens: 256,
  });
  setInputStory(response.data.choices[0].text);
};

const getDescription = async () => {
  const response = await openai.createCompletion({
    model: "text-davinci-003",
    prompt: `Create a description for ${inputName}.`,
    max_tokens: 256,
  });
  setInputDes(response.data.choices[0].text);
};

useEffect(() => {
  // 仅当inputName有值时才执行后续请求
  if (inputName) {
    getStory();
    getDescription();
  }
}, [inputName]);

为什么你的useCallback方案无效?

setInputName是异步操作,调用后inputName不会立刻更新,此时调用getStory获取到的还是更新前的空值。直接传递请求结果的方式可以彻底避开这个异步问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:01:05