web-dev-qa-db-ja.com

ネストされたReactコンポーネントのHOCによってラップされたコンポーネントの状態にアクセスするにはどうすればよいですか?

私は Enzyme を使用していますが、ドキュメントで指定された 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>を使用するときにローカルコンポーネントの状態にアクセスする方法が正確にわかりません。

おそらく私は無知なテストを行っていますか?テストでコンポーネントの状態を取得/設定するのは悪い習慣ですか? Enzymeにはコンポーネントの状態を取得/設定するメソッドがあるので、私はそれを想像することはできません。

<MemoryRouter>でラップされたコンポーネントの内部にアクセスする方法がわからない。

どんな助けでも大歓迎です!

17
indiesquidge

したがって、Enzymeの 最新リリース では、子コンポーネントの状態にアクセスするこの問題の潜在的な修正があるようです。

_<Foo>_があるとします(Reactルーターの_<Link>_の使用に注意してください)

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

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

注:次のコードは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にしかアクセスできませんでした。 setStateラッパーでChild関数を呼び出すこともできます。

浅くレンダリングされたテストで同様のパターンを使用できます

_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ノードで実行でき、浅いレンダリングされたノードを返します。


参照:

22
indiesquidge

私はこれを偶然見つけて修正したので、それはあなたたちにとって役に立つかもしれないと思いました。

私の場合、reduxに接続されているコンポーネントがあります。

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

connect()は明らかにHOCコンポーネントです。では、ここで「ComponentName」にどのようにアクセスしますか?

非常にシンプル:

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