如何用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
相关产品推荐
相关产品推荐

