是否可以在 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 作为 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 中使用自定义钩子,或者我做错了什么。

原文由 0x0 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 419
1 个回答

据我所知,组件中的钩子应该始终保持相同的顺序。并且由于 useEffect 有时会发生,并不是每个渲染都违反了 钩子的规则。在我看来,您的 useGetDocument 没有真正的需要。

我提出以下解决方案:

  1. 保持你的 useGetDocument 不变。
  2. 将您的组件更改为具有 useEffect document 作为依赖项的 —。

您的组件可能如下所示:

 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 (...)
}

原文由 ApplePearPerson 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进