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

How does one access state on a nested React component wrapped by an HOC?

我正在使用文档中提供的 Enzyme, and we can actually use the example 组件作为我的问题的基础。

假设这个 <Foo /> 组件使用来自 ReactRouter 的 <Link> 组件,因此我们需要将它包装在 <MemoryRouter> 中进行测试。

问题就出在这里。

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!
})

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

也许我在进行无知的测试?试图 get/set 组件状态测试中的不良做法?我无法想象它是,因为 Enzyme 有 getting/setting 组件状态的方法。

只是不确定应该如何访问包裹在 <MemoryRouter>.

中的组件的内部结构

如有任何帮助,我们将不胜感激!

因此,Enzyme 的 latest release 似乎可以解决访问子组件状态的问题。

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

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

  render () {
    return (
      <Link to='/'>Here is a link</Link>
    )
  }
}

Note: The following code is only available in 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!'
  })
})

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

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

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!'
  })
})

注意在浅层测试中使用dive,可以在单个非DOM节点上运行,并将return节点,浅渲染。


参考:

认为它可能对你们有用,因为我偶然发现了这个问题并进行了修复。

在我的例子中,我有一个连接到 redux 的组件。

class ComponentName extends Component {
...
}
export default connect(
  mapStateToProps,
  {
...
 }
)(ComponentName );

connect() 显然是一个 HOC 组件。 那么我们如何访问这里的 "ComponentName" 呢?

很简单:

component
    .find(ComponentName)
    .children()
    .first()
    .props() // returns ComponentName's props