4

I created custom hooks for get requests from the server. Below is an example

const usePost = (id: string) => {
    return useQuery(['posts', id], () => getPost(id))
}
const usePosts = () => {
    return useQuery(['posts'], () => getPosts())
}

However, I sometimes need to call multiple queries in a single file, so I would like to use the useQueries hook along with the custom hooks. But when I try to use the custom hooks as the queryFn, React throws me an error saying I can't call a hook inside the function 'queryFn'.

const queries = useQueries([
    {
        queryKey: 'posts',
        queryFn: () => usePosts
    },
    {
        queryKey: ['post', id],
        queryFn: () => usePost(id)
    }
])
// Failed to compile, 'usePost' is called in function 'queryFn' that is neither a React component nor custom hook

How would we be able to use useQueries with custom query hooks?

2
  • 1
    I'm not sure how react-query works, but you're calling the usePost hook in the second object, which is not allowed in React outside of a component render function. Note that, in your code, the first queryFn is a 'function that returns a function', while the other queryFn is not. I think queryFn: () => () => usePost(id) might be what you want. Commented Jul 26, 2022 at 12:55
  • 2
    @crizzis thank you, but there is still an error. The hook cannot be called inside a callback. Commented Jul 26, 2022 at 13:29

1 Answer 1

2

This is simply a restriction by the Rule of Hooks in React, that hooks can only be called inside React function components and other React custom hooks.

There are two options to overcome this issue in my opinion:

  1. combine usePost and usePosts in another custom hook
// useAllPosts.js
const useAllPosts = (id: string) => {
  const { data: post } = usePost(id);
  const { data: posts } = usePosts();

  return {
      post,
      posts
  }
}
  1. put the fetcher functions outside of the custom hooks so you can re-use them in other components:
// usePost.js
export const fetchPost = (id: string) => getPost(id);
const usePost = (id: string) => {
  return useQuery(['posts', id], fetchPost)
}

// usePosts.js
export const fetchPosts = () => getPosts();
const usePosts = () => {
  return useQuery(['posts'], () => getPosts())
}

// SomeComponent.jsx
import { fetchPost } from 'usePost';
import { fetchPosts } from 'usePosts';
function SomeComponent() {
  const queries = useQueries([
    {
      queryKey: 'posts',
      queryFn: fetchPosts
    },
    {
      queryKey: ['post', id],
      queryFn: fetchPost
    }
  ]);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.