【问题标题】:react-intl with react-testing-library gives Invalid hook call errorreact-intl 与 react-testing-library 给出了无效的钩子调用错误
【发布时间】:2023-09-30 03:05:01
【问题描述】:

在我们的项目中,我们使用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 命令运行测试,但是是的,这很棘手。我将在一个新项目上测试这个场景,看看是否会出现同样的错误,然后我会相应地更新这个问题。

标签: reactjs jestjs react-testing-library react-intl


【解决方案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'
  }

【讨论】:

    最近更新 更多