Reputation: 929
I am testing a React app with Jest & Enzyme. When I run npm run test
I get the error in UserContext.jsx
that is imported in MainPage.jsx
. How can I fix that?
Error message
Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app
11 | };
12 |
> 13 | export const useUserValue = () => useContext(UserContext);
| ^
UserContext.jsx
import React, {createContext, useContext, useReducer} from "react";
export const UserContext = createContext();
export const UserProvider = ({reducer, initialState, children}) => {
return(
<UserContext.Provider value={useReducer(reducer, initialState)}>
{children}
</UserContext.Provider>
)
};
export const useUserValue = () => useContext(UserContext);
MainPage.test.js
import React from 'react';
import 'jest-styled-components';
import { configure, shallow, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import MainPage from "./MainPage";
import {useUserValue} from "../Context/UserContext";
configure({adapter: new Adapter()});
describe('Main Page Component', () => {
it('exists', () => {
const wrapper = shallow(<MainPage />, {context: useUserValue()});
expect(wrapper).toMatchSnapshot();
});
});
MainPage.jsx
import React, {useEffect, useState} from 'react';
import {useUserValue} from "../Context/UserContext";
export default function MainPage(props) {
const [{ user }, dispatch] = useUserValue();
return (
<React.Fragment>
{user.name}
</React.Fragment>
);
}
Upvotes: 1
Views: 2710
Reputation: 223318
The error says what is the problem:
Hooks can only be called inside of the body of a function component
Here the hook is incorrectly used outside the component:
const wrapper = shallow(<MainPage />, {context: useUserValue()});
It should have been {context: someContext }
, but the problem is that Enzyme renderer accepts a context for legacy React context that cannot affect context consumers and functional components in particular.
Currently shallow
doesn't support context providers and needs to use mount
:
const wrapper = mount(
<UserContext.Provider value={...}>
<MainPage />
</UserContext.Provider>
);
Since useUserValue
is located in its own module, it could be tested separately and mocked in components where it's used, this way it can be used with shallow
.
This error can also occur if there are multiple copies or mismatching versions of React and ReactDOM, but this is not the case.
Upvotes: 1