[英]Is it possible to use a custom hook inside useEffect in React?
我有一個非常基本的自定義掛鈎,它接受一個路徑並從 firebase 返回一個文檔
import React, { useState, useEffect, useContext } from 'react';
import { FirebaseContext } from '../sharedComponents/Firebase';
function useGetDocument(path) {
const firebase = useContext(FirebaseContext)
const [document, setDocument] = useState(null)
useEffect(() => {
const getDocument = async () => {
let snapshot = await firebase.db.doc(path).get()
let document = snapshot.data()
document.id = snapshot.id
setDocument(document)
}
getDocument()
}, []);
return document
}
export default useGetDocument
然后我使用 useEffect 作為 componentDidMount/constructor 來更新狀態
useEffect(() => {
const init = async () => {
let docSnapshot = await useGetDocument("products/" + products[selectedProduct].id + "labels/list")
if(docSnapshot) {
let tempArray = []
for (const [key, value] of Object.entries(docSnapshot.list)) {
tempArray.push({id: key, color: value.color, description: value.description})
}
setLabels(tempArray)
} else {
setLabels([])
}
await props.finishLoading()
await setLoading(false)
}
init()
}, [])
但是,我從“throwInvalidHookError”得到了一個不變的違規,這意味着我違反了鈎子的規則,所以我的問題是你是否不能在 useEffect 中使用自定義鈎子,或者我是否做錯了其他事情。
據我所知,組件中的鈎子應該始終保持相同的順序。 而且由於useEffect
有時會發生,並不是每個渲染都違反hooks 的規則。 在我看來,您的useGetDocument
沒有真正的需要。
我提出以下解決方案:
useGetDocument
不變。document
作為依賴項的useEffect
。您的組件可能如下所示:
const Component = (props) => {
// Your document will either be null (according to your custom hook) or the document once it has fetched the data.
const document = useGetDocument("products/" + products[selectedProduct].id + "labels/list");
useEffect(() => {
if (document && document !== null) {
// Do your initialization things now that you have the document.
}
}, [ document ]);
return (...)
}
您不能在另一個鈎子中使用一個鈎子,因為它打破了Call Hooks from React function components
的規則,並且您傳遞給useEffect
的函數是一個常規的 javascript 函數。
您可以做的是在另一個自定義掛鈎中調用一個掛鈎。
您需要做的是在組件內部調用useGetDocument
並將結果傳遞到useEffect
依賴項數組中。
let docSnapshot = await useGetDocument("products/" + products[selectedProduct].id + "labels/list")
useEffect(() => { ... }, [docSnapshot])
這樣,當docSnapshot
發生變化時,您的useEffect
就會被調用。
當然你可以在其他的鈎子中調用鈎子。
不要從常規 JavaScript 函數調用 Hooks。 相反,您可以:
✅ 從 React 函數組件調用 Hooks。
✅ 從自定義 Hooks 調用 Hooks(我們將在下一頁了解它們)。
但...
您沒有在另一個鈎子中使用一個鈎子。
您意識到您傳遞給 useEffect 的是一個回調,因此您在回調主體內使用自定義掛鈎而不是掛鈎 (useEffect)。
如果你碰巧使用 ESLint 和 react-hooks 插件,它會警告你:
ESLint: React Hook "useAttachDocumentToProspectMutation" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.(react-hooks/rules-of-hooks)
話雖這么說,你根本不需要 useEffect 。 useGetDocument 不返回承諾,而是返回文檔。
掛鈎時
const document = useGetDocument("products/" + products[selectedProduct].id + "labels/list");
它將第一次返回 undefined ,然后根據@ApplePearPerson 的回答返回后續渲染的文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.