如何在HOC包装的嵌套React组件上访问状态?

ind*_*dge 17 jestjs react-router enzyme react-router-v4

我正在使用Enzyme,我们实际上可以使用文档中给出的示例组件作为我的问题的基础.

假设这个<Foo />组件使用了<Link>ReactRouter中的一个组件,因此我们需要将它包装在一个<MemoryRouter>for测试中.

这就是问题所在.

it('puts the lotion in the basket', () => {
  const wrapper = mount(
    <MemoryRouter>
      <Foo />
    </MemoryRouter>
  )

  wrapper.state('name') // this returns null! We are accessing the MemoryRouter's state, which isn't what we want!
  wrapper.find(Foo).state('name') // this breaks! state() can only be called on the root!
})
Run Code Online (Sandbox Code Playgroud)

因此,在使用时不确定如何访问本地组件状态<MemoryRouter>.

也许我正在进行无知的测试?试图在测试中获取/设置组件状态不良做法?我无法想象,因为Enzyme有获取/设置组件状态的方法.

只是不确定应该如何访问包含在其中的组件的内部<MemoryRouter>.

任何帮助将不胜感激!

ind*_*dge 19

因此,最近发布的Enzyme 似乎可以解决这个访问子组件状态的问题.

假设我们有<Foo>(注意使用React Router的<Link>)

class Foo extends Component {
  state = {
    bar: 'here is the state!'
  }

  render () {
    return (
      <Link to='/'>Here is a link</Link>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

注意:以下代码仅适用于Enzyme v3.

重新审视测试代码,我们现在可以编写以下内容

it('puts the lotion in the basket', () => {
  const wrapper = mount(
    <MemoryRouter>
      <Foo />
    </MemoryRouter>
  )

  expect(wrapper.find(Foo).instance().state).toEqual({
    bar: 'here is the state!'
  })
})
Run Code Online (Sandbox Code Playgroud)

使用wrapper.find(Child).instance()我们Child即使它是一个嵌套组件也可以访问状态.在之前的Enzyme版本中,我们只能访问instance根目录.您也可以setStateChild包装器上调用该函数!

我们可以使用与浅层渲染测试类似的模式

it('puts the lotion in the basket shallowly', () => {
  const wrapper = shallow(
    <MemoryRouter>
      <Foo />
    </MemoryRouter>
  )

  expect(wrapper.find(Foo).dive().instance().state).toEqual({
    bar: 'here is the state!'
  })
})
Run Code Online (Sandbox Code Playgroud)

注意dive浅层测试中的使用,它可以在单个非DOM节点上运行,并将返回浅层渲染的节点.


参考文献: