DEV Community

Emric
Emric

Posted on

Is it possible and/or bad practice to send hooks as props?

Consider we have the usePost custom hook. The hook calls an API and returns a post.

const usePost = () => {
  const [post, setPost] = useState();
  fetch('my-api/posts/1')
    .then(response => response.json())
    .then(json => setPost(json));
  return post;
}
Enter fullscreen mode Exit fullscreen mode

We also have the Post component, which simply renders the post title.

function Post() {
  const post = usePost();
  return <div>{post?.title}</div>
}
Enter fullscreen mode Exit fullscreen mode

Now I'd like to test the post component. I would like the test to not make any API calls. It is possible to achieve this with jest by using their mocks.

import { render } from '@testing-library/react';
import usePost from './usePost';
import Post from './Post'

jest.mock('./usePost');

const mockedUsePost = usePost as Jest.Mock;

it('shows the post title', async () => {
  const post = { title: 'My post' }
  mockedUsePost.mockImplementation(() => post);
  const { findByText } = render(<Post />)

  expect(await findByText(/My post/)).toBeInTheDocument();
})
Enter fullscreen mode Exit fullscreen mode

However I don't like this approach. I do not want to rely on jest mocks to test my components. I would like to instead create an inline mock implementation of the hook which I pass as a prop.

import { render } from '@testing-library/react';
import usePost from './usePost';
import Post from './Post'

it('shows the post title', async () => {
  const post = { title: 'My post' }
  const useMockedPost = () => post
  const { findByText } = render(<Post usePost={useMockedPost} />)

  expect(await findByText(/My post/)).toBeInTheDocument();
})
Enter fullscreen mode Exit fullscreen mode

Is there any negative side effects of doing so? Is it bad practice doing so?

I've extensively searched the web for answers but haven't found anything really helpful.

I'm thinking it might violate one of the hook rules. Namely it says "Don’t call Hooks inside loops, conditions, or nested functions.". One could argue that it is called in a condition as the component may be conditionally rendered. I would argue this will not be a problem since we never change the hook again during runtime.

Top comments (0)