【发布时间】:2017-05-08 10:10:06
【问题描述】:
在我的测试中,我想阻止我的主线程,直到我的一个组件完成其生命周期方法,通过componentDidUpdate(),在我触发一个导致它向自身添加子组件的事件之后。我该怎么做?
类似这样的:
describe('my <Component />', () => {
it('should do what I want when its button is clicked twice', () => {
const wrapper = mount(<Component />);
const button = wrapper.find('button');
// This next line has some side effects that cause <Component /> to add
// some children components to itself...
button.simulate('click', mockEvent);
// ... so I want to wait for those children to completely go through
// their lifecycle methods ...
wrapper.instance().askReactToBlockUntilTheComponentIsFinishedUpdating();
// ... so that I can be sure React is in the state I want it to be in
// when I further manipulate the <Component />
button.simulate('click', mockEvent);
expect(whatIWant()).to.be.true;
});
});
(我想这样做是因为,现在,我收到了这个警告:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op.
我相信我得到了它,因为我的测试导致我的组件更改其内部状态的速度比 React 的内部多线程魔法可以跟上的速度更快,所以当我第二次运行 button.simulate('click') 时,React 已经实例化新的子组件,但尚未完成安装它们。我认为等待 React 完成更新我的组件及其子组件是解决该问题的最佳方法。)
【问题讨论】:
-
点击处理程序是做什么的?所有状态更改都应该是同步的,除非你特别有一些计时器/异步的东西在进行。
-
DOM 更新也是同步的,除非你正在做一些奇怪的事情或使用 React 的异国风味。如果您的
setState警告是因为您的组件本身在挂载前执行了setState,我不会感到惊讶。 -
@Jacob 我正在使用第三方库,React Widgets。我的
<Component />有一个 React WidgetsDateTimePicker作为它的孩子之一,警告似乎是从DateTimePicker内部发出的。所以不幸的是,我完全确定我的事件会导致什么变化,而且我很容易无法尝试查看组件以确保它没有行为不端。 -
当我在浏览器中运行我的应用程序时,我没有收到警告,即使我执行了我在测试中模拟的相同操作,所以我相信这个问题是特定于我的测试环境如何交互的使用我的组件,而不是我的组件中的错误(尽管我很可能是错的)。
-
最后,你确定 React 应该同步更新组件吗?在a conversation I had in chat,有人suggested that's not the case。当我在
settimeout块中包围我的部分代码以在我模拟的事件之间提供一瞬间的时间时,警告消失了,这真的让我觉得 React 正在做一些我希望我的测试等待的异步操作为。
标签: javascript reactjs mocha.js chai enzyme