javascript - prevState 在 Enzyme 测试中未定义,但在组件中定义
问题描述
看到一个奇怪的问题,其中prevState
未定义componentDidUpdate
,但在组件在浏览器中运行时定义。
我在构造函数中设置了状态,并且在 componentDidUpdate 中检查了 on 的值prevState
。
componentDidUpdate(prevProps, prevState) {
const { showForm } = this.state;
if (prevState.showForm && !showForm) {
return this.input.current.focus();
}
}
这是酶测试:
it("should call focus on input if form was shown, and now form is open", () => {
component = mount(<Component {...props} />);
const prevProps = component.props();
const prevState = {
...component.state(),
showForm: true
};
const focusSpy = sinon.spy(component.instance().input.current, "focus");
component.instance().componentDidUpdate(prevProps, prevState);
expect(focusSpy).to.have.been.called;
});
这种方法有效 - 但只是因为我componentDidUpdate
从酶测试中调用并通过了它prevState
。理想情况下,我想避免这种情况——并且只定义 prevState——因为它是组件在浏览器中实际工作的时候。
处理这个的模式是什么?
解决方案
您的测试不应componentDidUpdate
显式调用。setState
下面是一个组件和测试,我已经验证了它只是多次调用来触发要测试的场景。
MyComp.js
import React from "react";
class MyComp extends React.PureComponent {
constructor(props) {
super(props);
this.state = { showForm: false };
this.input = React.createRef();
}
toggleShowForm = () => {
this.setState({ showForm: !this.state.showForm });
};
componentDidUpdate(prevProps, prevState) {
console.log(
"componentDidUpdate prevProps: " +
JSON.stringify(prevProps) +
"; prevState: " +
JSON.stringify(prevState) +
"; this.state: " +
JSON.stringify(this.state)
);
if (prevState.showForm && !this.state.showForm) {
console.log("setting focus");
this.input.current.focus();
}
}
render() {
return (
<>
<input type="text" ref={this.input} />
<br />
<button onClick={this.toggleShowForm}>Toggle showForm</button>
</>
);
}
}
export default MyComp;
MyComp.test.js
import React from "react";
import { mount } from "enzyme";
import MyComp from "./MyComp";
import sinon from "sinon";
it("should call focus on input if showForm goes from true to false", () => {
const myCompWrapper = mount(<MyComp />);
console.log("before first setState");
const focusSpy = sinon.spy(myCompWrapper.instance().input.current, "focus");
myCompWrapper.instance().setState({ showForm: true });
expect(focusSpy.called).toEqual(false);
console.log("before second setState");
myCompWrapper.instance().setState({ showForm: false });
expect(focusSpy.called).toEqual(true);
});
以下是此测试产生的控制台日志:
- 在第一次 setState 之前
- componentDidUpdate prevProps: {}; prevState: {"showForm":false}; this.state: {"showForm":true}
- 在第二个 setState 之前
- componentDidUpdate prevProps: {}; prevState: {"showForm":true}; this.state: {"showForm":false}
- 设置焦点
这是一个 CodeSandbox,您可以在其中执行此测试:
推荐阅读
- html - 为什么 Sublime Text 上下文菜单被禁用(下图)
- reactjs - MultiSelect 在值状态更改时不更新值(PrimeReact UI)
- python - 从 pyplot.plot 动作的循环中获取 ylim - 只有循环寄存器中的最后一个,其他一切都是 0、1
- javascript - 随着 Firebase RTDB 上的数据发生变化,实时更新 Html 表
- azure-devops - 错误找不到工作项类型产品待办事项项
- html - SVG 图像在 Safari 中未显示正确的字体
- google-cloud-platform - 谷歌云不允许我创建我的第一个具有管理员角色的项目
- java - Javax 验证 API。将父 bean 中的字段添加到验证消息
- npm-install - 卡在 npm install - M1 Mac
- javascript - Vuelidate根据服务器端响应显示错误消息?