Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use a custom hook inside useEffect in React?

I have a very basic custom hook that takes in a path an returns a document from 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 

Then I use useEffect as a componentDidMount/constructor to update the state

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()   }, []) 

However, I get an Invariant Violation from "throwInvalidHookError" which means that I am breaking the rules of hooks, so my question is whether you can't use custom hooks inside useEffect, or if I am doing something else wrong.

like image 706
0x0 Avatar asked Nov 27 '19 13:11

0x0


People also ask

Can we call Hooks from custom Hooks in React?

No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.

How do you call a custom hook inside an event handler?

You should leverage the useEffect hook's dependency in your custom useFetchMyApi hook to refresh the list of items. Add some local component state to represent the "currently" selected location. Use your button's onClick callback to update the state and trigger a rerender which then will rerun your custom hook.

Can I use useState in custom hook?

Rather than litter your components with a bunch of useState calls to keep track of the state of an async function, you can use our custom hook which takes an async function as an input and returns the value , error , and status values we need to properly update our UI.

How do you use custom Hooks in React JS?

Hooks are reusable functions. When you have component logic that needs to be used by multiple components, we can extract that logic to a custom Hook. Custom Hooks start with "use".


1 Answers

As far as I know, the hooks in a component should always be in the same order. And since the useEffect happens sometimes and not every render that does break the rules of hooks. It looks to me like your useGetDocument has no real need.

I propose the following solution:

  1. Keep your useGetDocument the same.
  2. Change your component to have a useEffect that has the document as a dependency.

Your component could look like the following:

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 (...) } 
like image 193
ApplePearPerson Avatar answered Sep 22 '22 11:09

ApplePearPerson