web-dev-qa-db-fra.com

Comment accéder à un état sur un composant imbriqué React enveloppé par un HOC?

J'utilise Enzyme , et nous pouvons réellement utiliser le composant exemple donné dans les documents comme fondement de ma question.

Supposons que ce <Foo /> le composant utilise un <Link> composant de ReactRouter et nous devons donc l'envelopper dans un <MemoryRouter> pour tester.

C'est ici que se trouve le problème.

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

Donc, vous ne savez pas exactement comment accéder à l'état du composant local lorsque vous utilisez <MemoryRouter>.

Peut-être que je fais un test ignorant? Essayer d'obtenir/définir l'état du composant est-il une mauvaise pratique dans les tests? Je ne peux pas imaginer que ce soit le cas, car Enzyme a des méthodes pour obtenir/définir l'état des composants.

Je ne sais pas comment on est censé accéder aux composants internes d'un composant enveloppé dans <MemoryRouter>.

Toute aide serait grandement appréciée!

17
indiesquidge

Il semble donc qu'avec la dernière version d'Enzyme, il existe un correctif potentiel pour ce problème d'accès à l'état sur un composant enfant.

Disons que nous avons <Foo> (Notez l'utilisation de React Router's <Link>)

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

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

Remarque: Le code suivant est uniquement disponible dans Enzyme v3.

Revisitant le code de test, nous pouvons maintenant écrire ce qui suit

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

En utilisant wrapper.find(Child).instance(), nous pouvons accéder à l'état de Child même s'il s'agit d'un composant imbriqué. Dans les versions précédentes d'Enzyme, nous ne pouvions accéder qu'à instance à la racine. Vous pouvez également appeler la fonction setState sur le wrapper Child!

Nous pouvons utiliser un modèle similaire avec nos tests rendus superficiellement

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

Notez l'utilisation de dive dans le test superficiel, qui peut être exécuté sur un seul nœud non DOM, et renverra le nœud, rendu superficiel.


Réfs:

22
indiesquidge

J'ai pensé que cela pourrait être utile pour vous, alors que je suis tombé dessus et que j'ai une solution.

Dans mon cas, j'ai un composant qui est connecté à redux.

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

connect () est évidemment un composant HOC. Alors, comment pouvons-nous accéder au "ComponentName" ici?

Très simple:

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