我正在用Jest&Enzyme测试React应用。运行npm run test
时,我在UserContext.jsx
中导入的MainPage.jsx
中收到错误。我该如何解决?
错误消息
不变违反:无效的挂钩调用。挂钩只能在功能组件的主体内部调用。可能由于以下原因之一而发生: 1.您的React和渲染器版本可能不匹配(例如React DOM) 2.您可能违反了《钩子规则》 3.您可能在同一应用程序中拥有多个React副本
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>
);
}
答案 0 :(得分:1)
该错误说明出了什么问题:
只能在函数组件的主体内部调用钩子
此处在组件外部未正确使用挂钩:
const wrapper = shallow(<MainPage />, {context: useUserValue()});
它本来应该是{context: someContext }
,但是问题在于Enzyme渲染器接受旧版React上下文的上下文,而该上下文不能特别影响上下文使用者和功能组件。
当前shallow
doesn't support context providers,需要使用mount
:
const wrapper = mount(
<UserContext.Provider value={...}>
<MainPage />
</UserContext.Provider>
);
由于useUserValue
位于其自己的模块中,因此可以对其进行单独测试,并可以在使用它的组件中对其进行模拟,因此可以与shallow
一起使用。
如果有多个副本或React和ReactDOM的版本不匹配,也会发生此错误,但这不是事实。