【问题标题】:Enzyme/Jest: Hooks can only be called inside of the body of a function componentEnzyme/Jest:只能在函数组件的主体内部调用 Hooks
【发布时间】:2021-09-12 23:59:51
【问题描述】:

假设我有一个这样的组件:

export function Click(props: { counter: number }) {
  const [ counter, setCounter ] = useState(props.counter);

  return (
    <header className="App-header">
      <h1 data-test="counter">{counter}</h1>

      <button onClick={() => setCounter(counter + 1)}>
        Click me
      </button>
    </header>
  );
}

而我的测试文件是这样的:

import React from 'react';
import { mount } from "enzyme";
import App, { Click } from './App';

class Setup<Props> {
  constructor(FunctionComponent: React.FC<Props>, props: Props) {
    return mount(
      <>
        {FunctionComponent(props)}
      </>
    )
  }
}

test("Doesn't work", () => {
  const wrapper = new Setup(Click, { counter: 0 });

  expect(wrapper.find(`[data-test="counter"]`)).toHaveLength(1);
});

这会返回一个错误: Hooks can only be called inside of the body of a function component.

但我真的不知道如何解决它。 你看,我不能使用功能组件,因为它会破坏目的。 我的想法是创建一个库来帮助我编写测试,所以我想使用类。

【问题讨论】:

    标签: reactjs typescript jestjs react-hooks enzyme


    【解决方案1】:

    要成为返回 JSX 的组件函数,应该使用 &lt;Component /&gt; 而不是 Component()

    hooks-rules 文档说:

    不要在循环、条件或嵌套函数中调用 Hooks。

    不要从常规 JavaScript 函数调用 Hooks。

    不要调用它们,渲染它们。

    例如

    App.tsx:

    import React from 'react';
    import { useState } from 'react';
    
    export function Click(props: { counter: number }) {
      const [counter, setCounter] = useState(props.counter);
    
      return (
        <header className="App-header">
          <h1 data-test="counter">{counter}</h1>
    
          <button onClick={() => setCounter(counter + 1)}>Click me</button>
        </header>
      );
    }
    

    App.test.tsx:

    import React from 'react';
    import { mount, ReactWrapper } from 'enzyme';
    import { Click } from './App';
    
    class Setup<Props> {
      constructor(FunctionComponent: React.FC<Props>, props: Props) {
        return mount(<FunctionComponent {...props} />);
      }
    }
    
    describe('68201330', () => {
      test('it should pass', () => {
        const wrapper = new Setup(Click, { counter: 0 }) as ReactWrapper;
        expect(wrapper.find(`[data-test="counter"]`)).toHaveLength(1);
      });
    });
    

    测试结果:

     PASS  examples/68201330/App.test.tsx (8.477 s)
      68201330
        ✓ it should pass (31 ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |   83.33 |      100 |      50 |   83.33 |                   
     App.tsx  |   83.33 |      100 |      50 |   83.33 | 11                
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        9.331 s, estimated 10 s
    

    【讨论】:

    • 我他妈的爱你!
    猜你喜欢
    • 2020-06-17
    • 2020-06-22
    • 2019-09-07
    • 2019-11-01
    • 2021-02-08
    • 1970-01-01
    • 2020-04-21
    • 2021-10-18
    相关资源
    最近更新 更多