Enzyme/Jest:只能在函数组件的主体内部调用 Hooks

Posted

技术标签:

【中文标题】Enzyme/Jest:只能在函数组件的主体内部调用 Hooks【英文标题】:Enzyme/Jest: Hooks can only be called inside of the body of a function component 【发布时间】: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.

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

【问题讨论】:

【参考方案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

【讨论】:

我他妈的爱你!

以上是关于Enzyme/Jest:只能在函数组件的主体内部调用 Hooks的主要内容,如果未能解决你的问题,请参考以下文章

如何在 javascript 中模拟内部 JSON 对象?

useLocation: Hooks 只能在函数组件的主体内部调用

错误 无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用

“无效的钩子调用。只能在函数组件的主体内部调用钩子”问题

无效的钩子调用错误:只能在函数组件的主体内部调用钩子

错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 【我还在用函数组件】