react-intl 与 react-testing-library 给出了无效的钩子调用错误
Posted
技术标签:
【中文标题】react-intl 与 react-testing-library 给出了无效的钩子调用错误【英文标题】:react-intl with react-testing-library gives Invalid hook call error 【发布时间】:2020-05-12 17:42:27 【问题描述】:在我们的项目中,我们使用react-intl
进行国际化。我们使用jest
作为测试框架,我们决定将我们的单元测试实用程序库从酶移到react-testing-library
。但是现在,由于没有浅渲染,我必须自己在测试中提供<IntlProvider ... />
,没有问题。但即使我这样做,当测试终端说Invalid hook call. Hooks can only be called inside of the body of a function component
但当我在本地运行项目时,没有错误只是按预期正常运行。 P.S 在测试中,Apollo 提供者正常工作。
FirstNameFor.test.tsx
import IntlProvider from 'react-intl';
import createMockClient from 'mock-apollo-client';
import ApolloProvider as ApolloProviderHooks from '@apollo/react-hooks';
import ApolloProvider from 'react-apollo';
const wrapper = (mockProps, mockClient) =>
return (
<ApolloProvider client=mockClient>
<ApolloProviderHooks client=mockClient>
<IntlProvider locale="en">
<FirstNameForm
handleNext=mockProps.handleNext
onboardingState=mockProps.onboardingState
setHelpContent=mockProps.setHelpContent
updateOnboardingState=mockProps.updateOnboardingState
/>
</IntlProvider>
</ApolloProviderHooks>
</ApolloProvider>
);
;
describe('FirstNameForm Container', () =>
afterEach(() =>
jest.clearAllMocks();
cleanup();
);
it('should match snapshot', () =>
// Arrange
const mockProps =
handleNext: jest.fn(),
onboardingState: ,
setHelpContent: jest.fn(),
updateOnboardingState: jest.fn(),
;
const mockClient = createMockClient();
// Act
const component = render(wrapper(mockProps, mockClient));
// Assert
expect(component).toMatchSnapshot();
);
);
FirstNameForm.tsx
export const FirstNameForm: React.FC<StepContentProps> = props =>
const [showMessageMutation] = useShowMessageMutation();
const intl = useIntl();
const formik = useFormik<FirstNameFormValues>(
...,
);
return <FirstNameFormComponent formik=formik intl=intl />;
;
终端截图
package.json
"private": true,
"proxy": "http://localhost:5000",
"version": "0.1.57",
"scripts":
"dev": "yarn graphql:generate && SKIP_PREFLIGHT_CHECK=true react-app-rewired start",
"build": "SKIP_PREFLIGHT_CHECK=true react-app-rewired build",
"testonly": "SKIP_PREFLIGHT_CHECK=true react-app-rewired test --env=jsdom",
"coverage": "SKIP_PREFLIGHT_CHECK=true react-app-rewired test --env=jsdom --coverage",
,
"jest":
"coveragePathIgnorePatterns": [
"/node_modules/",
"src/types/",
"src/config/analytics/mp.d.ts",
"src/config/analytics/ua.d.ts"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
,
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"resolutions":
"@types/react": "16.8.17"
,
"dependencies":
"@apollo/react-hooks": "3.1.3",
"animated-scroll-to": "1.2.2",
"apollo-cache": "1.3.2",
"apollo-cache-inmemory": "1.6.3",
"apollo-client": "2.6.3",
"apollo-link": "1.2.12",
"apollo-link-context": "1.0.18",
"apollo-link-error": "1.1.11",
"apollo-link-http": "1.5.15",
"apollo-link-ws": "1.0.18",
"apollo-utilities": "1.3.2",
"big.js": "5.2.2",
"copy-to-clipboard": "3.2.0",
"core-js": "3.0.1",
"date-fns": "1.30.1",
"downloadjs": "1.4.7",
"formik": "2.1.1",
"graphql": "14.3.0",
"graphql-subscriptions": "1.1.0",
"graphql-tag": "2.10.1",
"graphql-tools": "4.0.4",
"history": "4.9.0",
"intl": "1.2.5",
"js-cookie": "2.2.0",
"lodash": "4.17.11",
"owasp-password-strength-test": "1.3.0",
"qrcode.react": "0.9.3",
"query-string": "6.5.0",
"react": "16.8.6",
"react-apollo": "3.1.3",
"react-dom": "16.8.6",
"react-google-recaptcha": "1.1.0",
"react-intl": "3.1.8",
"react-router-dom": "5.1.0",
"recompose": "0.30.0",
"regenerator-runtime": "0.13.2",
"subscriptions-transport-ws": "0.9.16",
"validator": "10.11.0",
"victory": "34.0.0",
"yup": "0.27.0"
,
"devDependencies":
"@apollo/react-testing": "3.1.3",
"@babel/cli": "7.4.4",
"@babel/core": "7.4.4",
"@babel/preset-env": "7.4.4",
"@graphql-codegen/add": "1.8.1",
"@graphql-codegen/cli": "1.8.1",
"@graphql-codegen/fragment-matcher": "1.8.1",
"@graphql-codegen/typescript": "1.8.1",
"@graphql-codegen/typescript-operations": "1.8.1",
"@graphql-codegen/typescript-react-apollo": "1.8.1",
"@testing-library/react": "10.0.4",
"@testing-library/jest-dom": "5.8.0",
"@types/testing-library__react": "10.0.1",
"@types/big.js": "4.0.5",
"@types/downloadjs": "1.4.1",
"@types/enzyme": "3.10.5",
"@types/graphql": "14.2.0",
"@types/js-cookie": "2.2.2",
"@types/node": "12.0.0",
"@types/owasp-password-strength-test": "1.3.0",
"@types/prop-types": "15.7.1",
"@types/qrcode.react": "0.8.2",
"@types/query-string": "6.3.0",
"@types/react": "16.8.17",
"@types/react-dom": "16.8.4",
"@types/react-google-recaptcha": "1.0.0",
"@types/react-router-dom": "5.1.0",
"@types/react-test-renderer": "16.9.0",
"@types/recompose": "0.30.6",
"@types/validator": "10.11.0",
"@types/victory": "33.1.0",
"@types/ws": "6.0.1",
"@types/yup": "0.26.13",
"babel-loader": "8.0.6",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.2",
"enzyme-to-json": "3.4.4",
"jest-canvas-mock": "2.2.0",
"jest-localstorage-mock": "2.4.0",
"merge-graphql-schemas": "1.5.8",
"npm-run-all": "4.1.5",
"patch-package": "6.1.2",
"postinstall-postinstall": "2.0.0",
"react-app-rewired": "2.1.3",
"react-scripts": "3.3.0",
"react-test-renderer": "16.8.6",
"source-map-explorer": "1.8.0",
"ts-jest": "25.3.1",
"ts-node": "8.1.0",
"typescript": "3.5.3"
【问题讨论】:
我认为这可能与github.com/formatjs/formatjs/issues/1477有关。 你能给我们看看你的 package.json 吗?你检查过你是否在某个地方有重复的 react 版本吗? 分享你的 package.json 这个错误很棘手:|,你捆绑你的测试吗? 我使用coverage
命令运行测试,但是是的,这很棘手。我将在一个新项目上测试这个场景,看看是否会出现同样的错误,然后我会相应地更新这个问题。
【参考方案1】:
错误来自 React 本身,很可能与 react-intl
无关。
很有可能您有多个 React 实例发生冲突,出于某种原因,仅在测试环境中发生。我怀疑这可能与react-app-rewired
有关,但不确定。
official help doc 中的步骤应该有助于揭示重复的 React 是否是问题的根源。
如果是这个原因,这里有一些来自社区的***解决方案:
修改您的 webpack 配置以解析react
别名 (discussion)
resolve:
alias:
react: path.resolve('./node_modules/react'),
,
修改您的 webpack 配置以将 react
设置为外部 (PR example)
externals:
react: 'react'
或这些其他杂项之一approaches
【讨论】:
以上是关于react-intl 与 react-testing-library 给出了无效的钩子调用错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 React-intl 的 Redux-form 字段级验证和错误翻译
尝试导入错误:“addLocaleData”未从“react-intl”导出