react-hook-form中FormContext测试报错的解决方案咨询
Let's break down what's causing the crash and how to fix it step by step.
The Root Cause
Your test code has a critical violation of React Hook rules: you're calling useForm() directly inside beforeEach(), which is a plain JavaScript function, not a React component or custom Hook. React Hooks can only be invoked during the render phase of a component, so this immediately throws an error. Additionally, your UserReportQuestion component already creates its own useForm instance internally—wrapping it in another FormContext in the test is redundant and could cause conflicts.
Solution 1: Simplify the Test (No External FormContext Needed)
Since your component manages its own useForm state, you don't need to wrap it in an extra FormContext for the basic "renders without crashing" test. Just render the component directly, and mock other dependencies like useTranslation to avoid unrelated errors:
import React from 'react'; import UserReportQuestion from './UserReportQuestion'; import { render } from '@testing-library/react'; import { useTranslation } from 'react-i18next'; // Mock useTranslation to skip i18n setup in tests jest.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key) => key }), })); describe('(Component) UserReport', () => { it('Should render without crashing', () => { const { container } = render(<UserReportQuestion />); expect(container).toBeInTheDocument(); }); });
Solution 2: Provide FormContext Correctly (If Needed)
If your component ever uses useFormContext() to inherit form methods from a parent (even if it doesn't now), you need to provide the context from within a React component (where Hooks are allowed). Create a simple wrapper component for your tests:
import React from 'react'; import UserReportQuestion from './UserReportQuestion'; import { render } from '@testing-library/react'; import { useForm, FormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; jest.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key) => key }), })); // Wrapper to safely use useForm and provide FormContext const FormContextWrapper = ({ children }) => { const formMethods = useForm(); return <FormContext {...formMethods}>{children}</FormContext>; }; describe('(Component) UserReport', () => { it('Should render without crashing', () => { const { container } = render( <FormContextWrapper> <UserReportQuestion /> </FormContextWrapper> ); expect(container).toBeInTheDocument(); }); });
Solution 3: Mock React Hook Form Entirely
If you want to isolate the component from the actual react-hook-form implementation, mock the library properly (fixing your commented-out mock):
import React from 'react'; import UserReportQuestion from './UserReportQuestion'; import { render } from '@testing-library/react'; import { useTranslation } from 'react-i18next'; // Mock react-hook-form to return minimal dummy methods jest.mock('react-hook-form', () => ({ useForm: jest.fn(() => ({ handleSubmit: jest.fn(), // Add any other methods your component uses here })), FormContext: ({ children }) => <>{children}</>, // Pass through children without context logic })); jest.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key) => key }), })); describe('(Component) UserReport', () => { it('Should render without crashing', () => { const { container } = render(<UserReportQuestion />); expect(container).toBeInTheDocument(); }); });
Key Takeaways
- Never call React Hooks outside of a component or custom Hook—this violates React's rules for Hooks.
- Only wrap your component in
FormContextif it relies onuseFormContext()to inherit form state from a parent. - Always mock external dependencies like translation libraries to avoid unrelated test failures.
内容的提问来源于stack exchange,提问作者MaxwellLynn

