How to access state on a React nested component wrapped in HOC?

I use Enzyme , and we can use the sample component provided in the documentation as the basis for my question.

Suppose this <Foo/> component uses the <Link> component from ReactRouter, and so we need to wrap it in <MemoryRouter> for testing.

This is the problem.

 it('puts the lotion in the basket', () => { const wrapper = mount( <MemoryRouter> <Foo /> </MemoryRouter> ) wrapper.state('name') // this returns null! We are accessing the MemoryRouter state, which isn't what we want! wrapper.find(Foo).state('name') // this breaks! state() can only be called on the root! }) 

Thus, Iโ€™m not quite sure how to access the state of the local component when using <MemoryRouter> .

Maybe I'm doing an ignorant test? Is trying to get / set the state of a component a bad practice when testing? I canโ€™t imagine it, since Enzyme has methods for getting / setting the state of a component.

Just not sure how to access the internal components of the component, <MemoryRouter> in <MemoryRouter> .

Any help would be greatly appreciated!

+14
react-router react-router-v4 jestjs enzyme
source share
2 answers

So it seems that with the latest version of Enzyme, there is a potential fix for this issue of accessing the state of a child component.

Say we have <Foo> (note the use of the 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.

Revision of the test code, now we can write the following

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

Using wrapper.find(Child).instance() , we can access the state of the Child , even if it is a nested component. In previous versions of Enzyme, we could only access instance at the root. You can also call the setState function in the Child !

We can use a similar model with our shallow graded tests.

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

Pay attention to the use of dive in a shallow test, which can be run on one non-DOM node and will return a small-cutting node.


Refs:

+17
source share

I think it might be useful for you guys, since I stumbled upon this and fix it.

In my case, I have a component that is associated with Redux.

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

connect () is obviously a component of HOC. So how do we access the "ComponentName" here?

Very simple:

 component .find(ComponentName) .children() .first() .props() // returns ComponentName props 
0
source share

All Articles