enzyme: Get doesn't always return a react element

the get method for mounted components doesn’t always return a react element even though it says it does. if i create something with nested components, like this,

   let el = (
     <Parent><Child /></Parent>
   );
   let wrapper = mount(el);
   console.log(wrapper.get(0)); //Parent Component instance, not element
   console.log(typeof wrapper.get(0)); //object, not reactelement

  console.log(wrapper.find(Child).get(0)); //Child component instance, not element
  console.log(typeof wrapper.find(Child).get(0)); //object, not reactelement

is there a way to get the element?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 28 (18 by maintainers)

Most upvoted comments

ah got it. that’s good to know. i guess this isn’t a big deal then. the documentation should just change to reflect that it’s not necessarily a reactelement being returned

i think it was related to trying to match against a component with a method for a prop. i got it to work by passing in the actual method on the component that i was matching against.

  class Parent extends React.Component {
    constructor(props){
      super(props);
      this.foo = this.foo.bind(this);
    }

    foo(){
    }

    render(){
      return <Child foo={this.foo}/>;
    }
  }

  function Child(props){
    return <div className="abc" onClick={props.foo}>123</div>;
  }

  it('renders properly', function(){
    componentWrapper = mount(<FormParent />);
    expect(componentWrapper.contains(<div className="abc" onClick={componentWrapper.get(0).foo}>123</div>)).toBe(true);
  });

@ljharb so yeah, it does work, but so does passing the component instance

const component = wrapper.find(Foo).get(0)
const element = component._reactInternalInstance._currentElement
// wrapper2 identical to wrapper
wrapper2.contains(component) // true
wrapper.contains(element) // true

get does not return a ReactElement, it returns an instance of the component that exists at the passed index. You can see a failing test case here: enzyme-test-repo/blob/issue-497/test.js

get relies on getWrappedComponent from ReactWrapperComponent

    getWrappedComponent() {
      const component = this._reactInternalInstance._renderedComponent;
      const inst = component.getPublicInstance();
      if (inst === null) {
        return component._instance;
      }
      return inst;
    },

component._instance (which is returned in either case) is not a ReactElement, it’s an instance of the component that is being rendered. If you want the actual ReactElement then you need to use the internal instance which is available on _reactInternalInstance (See ReactInstanceMap) which holds a reference to the element at _currentElement.

IMO get() should not be returning the ReactElement. If you need access to the actual ReactElement then you can access it via

wrapper.get(0)._reactInternalInstance._currentElement

We should just update the docs so it doesn’t claim to return a ReactElement, which it’s never done AFAIK.

ah sorry. you’re right about about the typeof.

isValidElement returns false in both scenarios above. it only happens on mount though. not shallow.

here’s the parent class for reference.

  class Parent extends React.Component {
    constructor(props){
      super(props);
    }

    getChildContext(){
      return {
        foo: true,
        bar: this.props.bar
      };
    }

    render(){
      return this.props.children;
    }
  }

  Parent.childContextTypes = {
    bar: React.PropTypes.func.isRequired,
    foo: React.PropTypes.bool.isRequired
  };

and here’s what i passed to mount

<Parent bar={someMock}>
  <Child {...someProps} />
</FormParent>