等待React组件完成更新

Kev*_*ica 5 javascript mocha.js chai reactjs enzyme

在我的测试中,我想阻止我的主线程,直到我的一个组件完成其生命周期方法,然后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;
  });
});
Run Code Online (Sandbox Code Playgroud)

(我想这样做,因为,现在,我得到这个警告:

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.
Run Code Online (Sandbox Code Playgroud)

我相信我得到它是因为我的测试导致我的组件更快地改变其内部状态比React的内部多线程魔术可以跟上,所以当我button.simulate('click')第二次运行时,React已经实例化了新的子组件但是没有还没完成安装它们.我认为等待React完成更新我的Component及其子代是解决该问题的最佳方法.)

Kev*_*ica 4

尝试将您的expect()块包装在一个setImmediate()块中:

describe('my <Component />', () => {
  it('should do what I want when its button is clicked twice', (done) => {
    const wrapper = mount(<Component />);
    const button = wrapper.find('button');

    button.simulate('click', mockEvent);
    button.simulate('click', mockEvent);

    setImmediate(() => {
      expect(whatIWant()).to.be.true;
      done();
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

事情是这样的:为了处理异步性,Node 和大多数浏览器在幕后都有一个事件队列。每当某个东西(例如 Promise 或 IO 事件)需要异步运行时,JS 环境就会将其添加到队列的末尾。然后,每当一段同步代码完成运行时,环境就会检查队列,选择队列前面的内容并运行它。

setImmediate()将一个函数添加到队列的后面。一旦队列中当前的所有内容完成运行,传递给函数中的所有内容都setImmediate()将运行。因此,无论 React 正在异步执行什么操作,将expect()s 包装在 a 中setImmediate()都会导致您的测试等待,直到 React 完成其在幕后执行的任何异步工作。

这是一个很好的问题,包含有关以下内容的更多信息setImmediate()setImmediate vs. nextTick

setImmediate()这是Node 中的文档: https ://nodejs.org/api/timers.html#timers_setimmediate_callback_args