Enzyme/Jest: Hooks只能在函数组件内部调用
Enzyme/Jest: Hooks can only be called inside of the body of a function component
假设我有这样一个组件:
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);
});
这returns一个错误:
Hooks can only be called inside of the body of a function component.
但是我真的不知道怎么解决。
你看,我不能使用功能组件,因为它会破坏目的。
我的想法是创建一个库来帮助我编写测试,所以我想使用 类.
要成为返回 JSX 的组件函数,应该用作 <Component />
而不是 Component()
。
hooks-rules 医生说:
Don’t call Hooks inside loops, conditions, or nested functions.
Don’t call Hooks from regular JavaScript functions.
不要调用它们,渲染它们。
例如
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
假设我有这样一个组件:
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);
});
这returns一个错误:
Hooks can only be called inside of the body of a function component.
但是我真的不知道怎么解决。 你看,我不能使用功能组件,因为它会破坏目的。 我的想法是创建一个库来帮助我编写测试,所以我想使用 类.
要成为返回 JSX 的组件函数,应该用作 <Component />
而不是 Component()
。
hooks-rules 医生说:
Don’t call Hooks inside loops, conditions, or nested functions.
Don’t call Hooks from regular JavaScript functions.
不要调用它们,渲染它们。
例如
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