gpt4 book ai didi

javascript - 在 react 测试渲染器中调用 Prop 回调不会更新 Hook

转载 作者:行者123 更新时间:2023-11-30 19:41:20 33 4
gpt4 key购买 nike

我正在尝试弄清楚如何测试使用钩子(Hook)来跟踪状态的 React 函数组件。我遇到的问题是当我调用传递给输入组件的 onChange prop 函数时,我的 useState Hook 的值没有更新,所以当我触发表单提交,结果不反射(reflect)状态变化。

这是我正在测试的组件:

import React, { useState, ChangeEvent, FormEvent } from 'react';
import styled from '../styled';
import Column from './Column';
import BlockButton from './BlockButton';
import Input from './Input';
import Form from './Form';
import InputRow from './InputRow';

export type LoginFormOnSubmit = (result: LoginFormResult) => any;
export interface LoginFormResult {
employeeId: string;
password: string;
}
export interface LoginFormProps {
onSubmit?: LoginFormOnSubmit;
}

const LoginForm: React.FunctionComponent<LoginFormProps> = props => {
const { onSubmit, ...rest } = props;
const [employeeId, setEmployeeId] = useState('');
const [password, setPassword] = useState('');

function handleEmployeeIdChange(event: ChangeEvent<HTMLInputElement>) {
setEmployeeId(event.currentTarget.value);
}

function handlePasswordChange(event: ChangeEvent<HTMLInputElement>) {
setPassword(event.currentTarget.value);
}

function handleSubmit(event: FormEvent<HTMLFormElement>) {
if(onSubmit) {
onSubmit({
employeeId,
password,
});
}
}

return (
<Column {...rest}>
<h1>SHIFT LEDGER LOGON</h1>
<Form onSubmit={handleSubmit}>
<InputRow>
<label>Employee ID:</label>
<Input
type="text"
value={employeeId}
onChange={handleEmployeeIdChange}
data-testid="employee-id-input"
/>
</InputRow>
<InputRow>
<label>Password:</label>
<Input
type="password"
value={password}
onChange={handlePasswordChange}
data-test-id="password-input"
/>
</InputRow>
<BlockButton data-testid="submit-button">Enter</BlockButton>
</Form>
</Column>
);
};

export default styled(LoginForm)`
background-color: #F0EBDF;
justify-content: center;
flex: 1;

h1 {
text-align: center;
}

${Form} {
align-items: center;
}

label {
width: 150px;
}
`;

这是我的测试:

import React from 'react';
import sinon from 'sinon';
import TestRenderer, { act } from 'react-test-renderer';
import LoginForm from '../LoginForm';
import Form from '../Form';

describe('components/LoginForm', () => {
test('Should be able to edit employee id', async () => {
const onSubmit = sinon.fake();
const employeeId = 'test id';
const rendered = TestRenderer.create(<LoginForm onSubmit={onSubmit}/>);


act(() => {
const wrapper = rendered.root;
const employeeIdInput = wrapper.findByProps({ 'data-testid': 'employee-id-input' });

employeeIdInput.props!.onChange({
currentTarget: {
value: employeeId,
},
});

wrapper.findByType(Form).props.onSubmit({
preventDefault: sinon.fake(),
});
});

expect(onSubmit.calledOnce).toBeTruthy();
expect(onSubmit.args).toEqual([[
{
employeeId,
password: '',
}
]]);
});
});

我看到的错误:

  ● components/LoginForm › Should be able to edit employee id

expect(received).toEqual(expected)

Difference:

- Expected
+ Received

Array [
Array [
Object {
- "employeeId": "test id",
+ "employeeId": "",
"password": "",
},
],
]

42 | });
43 |
> 44 | expect(onSubmit.calledOnce).toBeTruthy();
| ^
45 | expect(onSubmit.args).toEqual([[
46 | {
47 | employeeId,

at react_test_renderer_1.act (src/components/__tests__/LoginForm.test.tsx:44:33)
at batchedUpdates (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12492:12)
at Object.act (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13146:18)
at Object.test (src/components/__tests__/LoginForm.test.tsx:29:5)

一些额外的信息:

  • typescript 3.3.3
  • react 16.8.2
  • react -dom 16.8.2
  • react 测试渲染器 16.8.5
  • 开 Jest 24.3.1

最佳答案

看起来问题是状态在act函数期间不更新,它只在act之后更新> 完成

这是一个简单的例子:

import React, { useState } from 'react';
import TestRenderer, { act } from 'react-test-renderer';

function Example(props) {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)} data-test-id="increment">
Increment
</button>
<button onClick={() => props.submit(count)} data-test-id="submit">
Submit
</button>
</div>
);
}

test('Example', () => {
const submitSpy = jest.fn();
const rendered = TestRenderer.create(<Example submit={submitSpy} />);

act(() => {
rendered.root.findByProps({ 'data-test-id': 'increment' }).props.onClick(); // increment
rendered.root.findByProps({ 'data-test-id': 'submit' }).props.onClick(); // submit
expect(rendered.root.findByType('p').props.children).toBe(0); // <= still 0
expect(submitSpy).toHaveBeenLastCalledWith(0); // <= still 0
});

expect(rendered.root.findByType('p').props.children).toBe(1); // <= NOW it's 1
rendered.root.findByProps({ 'data-test-id': 'submit' }).props.onClick(); // submit again
expect(submitSpy).toHaveBeenLastCalledWith(1); // Success!
});

所以看起来在 act 之后提交表单而不是 act 期间可能会解决问题.

关于javascript - 在 react 测试渲染器中调用 Prop 回调不会更新 Hook ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55365287/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com