为什么setState中断componentDidUpdate?

问题描述 投票:1回答:1

我有这个组件(简化版):

export default class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoading: false,
            data: {}
        };
    }

    componentDidUpdate(prevProps, prevState) {
        if(this.props.time && this.props.time !== prevProps.time){
           this.setState({
             isLoading: true
           })
           fetch(...).then(data => {
             this.setState({
               data: data
               isLoading:false
             }
        }
    }
    render(){
      {isLoading, data} = this.state;
      return (isLoading ? /*show spinner*/ : /* show data*/);
    }

}

该组件有效:它在获取数据时显示一个微调器,然后显示数据。

我正在尝试使用jest和酶来测试它:

test('Mounted correctly', async() => {
   let myComponent = mount(<MyComponent time='01-01-18'/>);
   myComponent.setProps({time: '02-01-18'}); //necessary to call componentDidUpdate
   expect(myComponent.state()).toMatchSnapshot();
}

据我所知,为了打电话给componentDidUpdate,你必须打电话给setProslink)。但是,在调试器之后,当命中时调用结束:

       this.setState({
         isLoading: true
       })

这有点预期,问题是快照是:

Object {
  "isLoading": true
  "data": {}
}

当然,这是我不想要的东西。我怎么解决这个问题?

更新:我找到了一个(难看的)解决方案!

问题是我们要测试的是这个setState已完成:

         this.setState({
           data: data
           isLoading:false
         }

现在,即使通过设置await myComponent.setProps({time: '02-01-18'});(如其中一个答案中所建议的),也不会发生这种情况,因为它不会等待上述setState创建的新异步调用。

我找到的唯一解决方案是将回调函数传递给props并在setState完成后调用它。回调函数包含我们想要的expect

所以这是最终的结果:

test('Mounted correctly', async() => {
   let myComponent = mount(<MyComponent time='01-01-18'/>);
   const callBackAfterLastSetStateIsCompleted = () => {
      expect(topAsins.state()).toMatchSnapshot();
   }
   myComponent.setProps({time: '02-01-18', testCallBack: callBackAfterLastSetStateIsCompleted}); //necessary to call componentDidUpdate
   expect(myComponent.state()).toMatchSnapshot();
}

并将组件代码修改为:

         this.setState({
           data: data
           isLoading:false
         },this.props.testCallBack);

但是,正如您所看到的,我正在修改生产中的组件仅用于测试目的,这是非常难看的。

现在,我的问题是:我该如何解决这个问题?

reactjs unit-testing enzyme jest
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.