是否可以在 React 中使用 useEffect 中的自定义钩子?



我有一个非常基本的自定义钩子,它采用从 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 作为组件 DidMount/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有时会发生,而不是每个渲染都会破坏钩子的规则。在我看来,你的useGetDocument没有真正的需要。

我提出以下解决方案:

  1. 保持useGetDocument不变。
  2. 将组件更改为具有将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(我们将在下一页了解它们(。

但。。。

您没有在另一个钩子中使用钩子。

你意识到你传递给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");

它将在第一次返回未定义,然后根据@ApplePearPerson的答案进行后续渲染的文档。

相关内容

  • 没有找到相关文章

最新更新