将 Async 函数放入 useEffect 后出现错误
Getting error after I put Async function in useEffect
在 useEffect 函数中,如果我只提到 getResults 函数变量,应用程序不会崩溃。但是当我在下面的代码中调用它时,我得到了这些错误:
react-dom.development.js:21857 Uncaught TypeError: destroy is not a
function
和
Consider adding an error boundary to your tree to customize error handling behavior.
function App() {
const [foods, setFoods] = useState([]);
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => getResponse());
const getResponse = async () => {
const response = await fetch(sampleRequest);
const data = await response.json();
setFoods(data.hits);
};
let query = "Tomato";
let sampleRequest = `https://api.edamam.com/search?q=${query}&app_id=${"1811484f"}&app_key=${"9cac93361efc99e2ebfbb8a453882af8"}`;
return (
<div className="App">
<div className="main">
<div className="navbars">
{" "}
<Navbars></Navbars>
</div>
<div className="listings">
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
</div>
<div className="footer">
<h5>Made By YoYo Strangler in 2019</h5>
</div>
</div>
</div>
);
}
export default App;
您正在 return 从 useEffect
函数调用 getResponse()
的结果。如果你 return 来自 useEffect
的任何东西,它必须是一个函数。将您的代码更改为此应该可以修复它,因为您不再 returning 来自 useEffect
函数的任何内容。
useEffect(() => {
getResponse();
});
useEffect
清理函数
如果您 return 来自 useEffect
钩子函数的任何东西,它必须是一个 清理函数 。当组件卸载时,此函数将 运行。这可以被认为大致等同于 class 组件中的 componentWillUnmount
生命周期方法。
useEffect(() => {
doSomething();
return () => {
console.log("This will be logged on unmount");
}
});
异步函数实际上只是 promise 的语法糖,所以当您调用异步函数时,它会返回一个 promise。
相反,您可以像这样用 IIFE(立即调用的函数表达式)包装异步函数,这样就不会向 useEffect
返回任何内容并用作清理函数:
useEffect(() => {
(async () => getResponse())();
});
编辑:或正如@json 在下面的评论中指出的那样。只是:
useEffect(() => { getResponse() });
上面的简单代码导致您的应用程序崩溃的原因是 useEffect
挂钩、async
函数和 shorthand 箭头函数语法的工作方式。
useEffect 挂钩的一个功能是清理功能。如果你 return 来自 useEffect 钩子函数的任何东西,它一定是一个清理函数。当组件卸载时,此函数将 运行。这可以被认为大致等同于 class components.
中的 componentWillUnmount 生命周期方法。
在JavaScript中,标有async
关键字的函数允许使用await
特性,它允许开发者在等待异步任务执行时暂停函数的执行结束。异步函数也总是 return 一个 Promise;如果该函数还没有 return,return 值会自动包装在 Promise 中。
最后,shorthand 箭头函数语法允许开发人员省略函数体周围的大括号,这对于简单的单行代码很有用。函数体的值自动成为箭头函数的 return 值,不再需要 return
关键字。此功能称为隐式 Return.
现在,这些花絮是如何聚集在一起导致如此神秘的错误的?简单的说,getResponse
的值,也就是一个Promise,在useEffect hook中变成了箭头函数的return的值。还记得 useEffect 钩子期望清理函数被 returned 吗? Promise 不是函数。所以 React 会出错并产生错误。
要修复您的应用,请更改 useEffect 箭头函数以添加大括号并删除隐式 Return,如图所示:
useEffect(() => {
getResponse();
});
现在,useEffect 钩子 returns undefined
中的箭头函数是可以接受的,它告诉 React 不需要清理函数。这将解决问题,但如果 React 在发生这种情况时给出更有用的错误消息,那就太好了!
我像这样使用了 IIFE,而且成功了!!-
之前是这样的-
useEffect(async ()=>{
const awesome_value = await AsyncStorage.getItem('awesome')
setAwesome(awesome_value)
},[]);
现在我改成了这个-
useEffect( ()=>{
(async() => {const awesome_value = await AsyncStorage.getItem('awesome')
setAwesome(awesome_value)} ) ();
},[]);
在 useEffect 函数中,如果我只提到 getResults 函数变量,应用程序不会崩溃。但是当我在下面的代码中调用它时,我得到了这些错误:
react-dom.development.js:21857 Uncaught TypeError: destroy is not a function
和
Consider adding an error boundary to your tree to customize error handling behavior.
function App() {
const [foods, setFoods] = useState([]);
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => getResponse());
const getResponse = async () => {
const response = await fetch(sampleRequest);
const data = await response.json();
setFoods(data.hits);
};
let query = "Tomato";
let sampleRequest = `https://api.edamam.com/search?q=${query}&app_id=${"1811484f"}&app_key=${"9cac93361efc99e2ebfbb8a453882af8"}`;
return (
<div className="App">
<div className="main">
<div className="navbars">
{" "}
<Navbars></Navbars>
</div>
<div className="listings">
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
<Listing></Listing>
</div>
<div className="footer">
<h5>Made By YoYo Strangler in 2019</h5>
</div>
</div>
</div>
);
}
export default App;
您正在 return 从 useEffect
函数调用 getResponse()
的结果。如果你 return 来自 useEffect
的任何东西,它必须是一个函数。将您的代码更改为此应该可以修复它,因为您不再 returning 来自 useEffect
函数的任何内容。
useEffect(() => {
getResponse();
});
useEffect
清理函数
如果您 return 来自 useEffect
钩子函数的任何东西,它必须是一个 清理函数 。当组件卸载时,此函数将 运行。这可以被认为大致等同于 class 组件中的 componentWillUnmount
生命周期方法。
useEffect(() => {
doSomething();
return () => {
console.log("This will be logged on unmount");
}
});
异步函数实际上只是 promise 的语法糖,所以当您调用异步函数时,它会返回一个 promise。
相反,您可以像这样用 IIFE(立即调用的函数表达式)包装异步函数,这样就不会向 useEffect
返回任何内容并用作清理函数:
useEffect(() => {
(async () => getResponse())();
});
编辑:或正如@json 在下面的评论中指出的那样。只是:
useEffect(() => { getResponse() });
上面的简单代码导致您的应用程序崩溃的原因是 useEffect
挂钩、async
函数和 shorthand 箭头函数语法的工作方式。
useEffect 挂钩的一个功能是清理功能。如果你 return 来自 useEffect 钩子函数的任何东西,它一定是一个清理函数。当组件卸载时,此函数将 运行。这可以被认为大致等同于 class components.
中的 componentWillUnmount 生命周期方法。在JavaScript中,标有async
关键字的函数允许使用await
特性,它允许开发者在等待异步任务执行时暂停函数的执行结束。异步函数也总是 return 一个 Promise;如果该函数还没有 return,return 值会自动包装在 Promise 中。
最后,shorthand 箭头函数语法允许开发人员省略函数体周围的大括号,这对于简单的单行代码很有用。函数体的值自动成为箭头函数的 return 值,不再需要 return
关键字。此功能称为隐式 Return.
现在,这些花絮是如何聚集在一起导致如此神秘的错误的?简单的说,getResponse
的值,也就是一个Promise,在useEffect hook中变成了箭头函数的return的值。还记得 useEffect 钩子期望清理函数被 returned 吗? Promise 不是函数。所以 React 会出错并产生错误。
要修复您的应用,请更改 useEffect 箭头函数以添加大括号并删除隐式 Return,如图所示:
useEffect(() => {
getResponse();
});
现在,useEffect 钩子 returns undefined
中的箭头函数是可以接受的,它告诉 React 不需要清理函数。这将解决问题,但如果 React 在发生这种情况时给出更有用的错误消息,那就太好了!
我像这样使用了 IIFE,而且成功了!!-
之前是这样的-
useEffect(async ()=>{
const awesome_value = await AsyncStorage.getItem('awesome')
setAwesome(awesome_value)
},[]);
现在我改成了这个-
useEffect( ()=>{
(async() => {const awesome_value = await AsyncStorage.getItem('awesome')
setAwesome(awesome_value)} ) ();
},[]);