Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm using Enzyme, and we can actually use the example component given in the docs as a foundation for my question.

Let's assume this <Foo /> component uses a <Link> component from ReactRouter and thus we need to wrap it in a <MemoryRouter> for testing.

Herein lies 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's state, which isn't what we want!
  wrapper.find(Foo).state('name') // this breaks! state() can only be called on the root!
})

So, not exactly sure how to access local component state when using <MemoryRouter>.

Perhaps I'm performing an ignorant test? Is trying to get/set component state bad practice in testing? I can't imagine it is, as Enzyme has methods for getting/setting component state.

Just not sure how one is supposed to access the internals of a component wrapped in <MemoryRouter>.

Any help would be greatly appreciated!

like image 970
indiesquidge Avatar asked Jul 07 '17 21:07

indiesquidge


People also ask

How do you wrap a component in react?

To create wrapper components, you'll first learn to use the rest and spread operators to collect unused props to pass down to nested components. Then you'll create a component that uses the built-in children component to wrap nested components in JSX as if they were HTML elements.

Which methods are called when the state or props of a component is changed?

An update can be caused by changes to props or state. These methods are called in the following order when a component is being re-rendered: static getDerivedStateFromProps() shouldComponentUpdate() render()

What is the process of sending props from a higher level component to a lower level component called?

Prop drilling refers to the process of sending props from a higher-level component to a lower-level component. To pass the props down from the topmost component, we must do something like this: However, prop drilling can become an issue in itself because of its repetitive code.

What is component in react?

Components in React basically return a piece of JSX code that tells what should be rendered on the screen. In React, we mainly have two types of components: Functional Components: Functional components are simply javascript functions. We can create a functional component in React by writing a javascript function.


1 Answers

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

Let's say we have <Foo> (note the use of React Router's <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.

Revisiting the test code, we are now able to 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 are able to access Child's state even though it is a nested component. In previous Enzyme versions we could only access instance on the root. You can also call the setState function on the Child wrapper as well!

We can use a similar pattern with our shallowly rendered 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!'
  })
})

Note the use of dive in the shallow test, which can be run on a single, non-DOM node, and will return the node, shallow-rendered.


Refs:

  • https://github.com/airbnb/enzyme/issues/361
  • https://github.com/airbnb/enzyme/issues/1289
  • https://github.com/airbnb/enzyme/blob/master/docs/guides/migration-from-2-to-3
like image 134
indiesquidge Avatar answered Sep 30 '22 20:09

indiesquidge