0

I'm writing a custom hook to fetch some enums defined in my GraphQL schema for use in form fields. The enum values obviously don't change all that frequently but I wanted to make them available to any form component (or any component). My problem is that no matter how I fire the query, my hook is always returning its initial state. There are several examples of data fetching in custom hooks, and they all follow a pretty similar pattern, e.g., something like this answer: Fetch data with a custom React hook

I first wrote the hook to use Apollo's useQuery(), and I set data as a dependency of useEffect().

export const useFormFieldEnums = () => {
  const [ enums, setEnums ] = useState( null )

  const ENUMS_QUERY = gql`
    query FormFieldEnums {
      mailingAddressTypes: __type(name: "MailingAddressType") {
        name
        enumValues {
          name
        }
      }
      emailTypes: __type(name: "EmailType") {
        name
        enumValues {
          name
        }
      }
      phoneTypes: __type(name: "PhoneType") {
        name
        enumValues {
          name
        }
      }
    }
  `

  const { data } = useQuery( ENUMS_QUERY )

  useEffect(() => {
    if ( data ) {
      // result = wrangle data into desired shape
      setEnums( result )
    }
  }, [data])

  return enums
}

Done this way, the query is dispatched (I see the request and response in the browser's network tab), but return enums isn't executed again after the query resolves with data.

I thought that perhaps the data dependency of useEffect() was responsible, so I tried using the query() method of Apollo Client directly, via the useApolloClient() hook, to allow the query to be dispatched asynchronously and have no dependencies for useEffect(). Done this way, the query doesn't even appear to be executed. (?)

export const useFormFieldEnums = () => {
  const [ enums, setEnums ] = useState( null )
  const client = useApolloClient()

  const ENUMS_QUERY = gql`
    query FormFieldEnums {
      mailingAddressTypes: __type(name: "MailingAddressType") {
        name
        enumValues {
          name
        }
      }
      emailTypes: __type(name: "EmailType") {
        name
        enumValues {
          name
        }
      }
      phoneTypes: __type(name: "PhoneType") {
        name
        enumValues {
          name
        }
      }
    }
  `

  useEffect(async() => {
    try {
      const { data } = await client.query({ query: ENUMS_QUERY })
      // result = wrangle data into desired shape
      setEnums( result )
    } catch ( error ) {
      console.error( error )
    }
  }, [])

  return enums
}

In both cases I'm always getting the initial state of enums back from the hook, even though return enums should be executed each time the value of enums changes. Presumably, setEnums( result ) is not getting called, but I can't figure out why.

Any help is appreciated, thanks!

diekunstderfuge
  • 521
  • 1
  • 7
  • 15
  • `// result = wrangle data into desired shape` is not enough when looking for errors ... details ... you can always `console.log(data, result)` to check if effect code is run – xadm Jun 17 '20 at 22:38
  • That omitted code is simply some `map` calls and object property assignment. It's not really relevant to the issue. What is a problem is that I don't see _any_ `console.log()` statements that I've put inside the `useEffect()` call. – diekunstderfuge Jun 18 '20 at 13:45

0 Answers0