Enzyme中外层wrapper修改state/props后,内层组件实例未更新的原因?
Why does reusing a previously found Enzyme wrapper not reflect state updates?
我太懂你踩的这个坑了!这其实是Enzyme shallow渲染里一个很容易忽略的特性——你第一次用wrapper.find()拿到的ShallowWrapper是组件树当时状态的快照,不是实时绑定的引用。
咱们结合你的测试代码来拆解:
- 第一次调用
wrapper.setState后,你立刻find并断言,结果正确,因为这时候的Wrapper是基于最新渲染的组件树生成的; - 第二次更新状态后,你直接复用之前存的
bootstrapTableWrapper——这个对象还停留在你第一次find时的状态,根本不知道外层组件已经重新渲染了,所以拿到的data还是升序的; - 当你重新执行
wrapper.find('BootstrapTable'),Enzyme会重新遍历当前的组件树,生成一个新的、对应最新状态的Wrapper,这时候断言自然就正确了。
本质原因
Enzyme的find()方法返回的ShallowWrapper对象,内部保存了调用那一刻组件的DOM/组件树结构、props、state等信息。它就像你给组件树拍了一张静态照片,之后组件再怎么更新,这张旧照片不会自动同步变化。只有重新调用find(),相当于重新拍一张照片,才能拿到最新的组件状态。
实践建议
- 每次组件状态(或props)更新后,务必重新调用
find()获取最新的Wrapper,不要复用之前保存的实例; - 可以封装一个小辅助函数来简化重复查询:
这样每次需要断言时,直接调用这个函数就能拿到最新的组件Wrapper;const getBootstrapTable = () => wrapper.find('BootstrapTable');
你的代码示例(格式化后)
MyTable.js组件代码
render () { // I manipulate this.props here and assign some of them to bootstrapTableProps return ( <div> <Header /> <BootstrapTable {...bootstrapTableProps}/> </div> ) }
MyTable.spec.js测试代码
let wrapper = shallow( <MyTable {...someProps} /> ); // change state wrapper.setState({sortName: 'timestamp', sortOrder: 'asc'}); let bootstrapTableWrapper = wrapper.find('BootstrapTable'); let timestamps = bootstrapTableWrapper.prop('data').map(row => row.timestamp); expect(timestamps).to.be.ascending; // CORRECT, sorted to be ascending // change state second time wrapper.setState({sortName: 'timestamp', sortOrder: 'desc'}); let timestamps = bootstrapTableWrapper.prop('data').map(row => row.timestamp); expect(timestamps).to.be.descending; // ERROR, still ascending // recreate the inner wrapper bootstrapTableWrapper = wrapper.find('BootstrapTable'); let timestamps = bootstrapTableWrapper.prop('data').map(row => row.timestamp); expect(timestamps).to.be.descending; // CORRECT, descending
内容的提问来源于stack exchange,提问作者croraf
相关产品推荐
相关产品推荐

