Enzyme: Ref not forwarded by WrappedComponent

Created on 4 Oct 2018  ยท  9Comments  ยท  Source: enzymejs/enzyme

Describe the bug
Ref is not being forwarded by WrappedComponent to the wrapped component

To Reproduce

// A.js
class A extends React.PureComponent {
  render () {
    return <div>FOO</div>
  }
}

// B.js
class B extends React.PureComponent {
  render () {
    return <A ref={this.props.forwardedRef} />
  }
}

const BForwarded = React.forwardRef((props, ref) => (
  <B {...props} forwardedRef={ref} />
))

// B.test.js
it('should forward ref to A', () => {
  const ref = React.createRef()
  mount(<BForwarded ref={ref} />)
  expect(ref.current).toBeInstanceOf(A)
})
FAIL  B.test.js
  โ— should forward ref to A

    expect(value).toBeInstanceOf(constructor)

    Expected constructor: A
    Received constructor: WrapperComponent

In the example above, ref.current is an instance of WrapperComponent which is an internal enzyme class returned by the createMountWrapper HOC.

library | version
-- | --
Enzyme | 3.6.0
React | 16.4.2

Expected behavior
The ref should be passed from B to A therefore the test above should not fail

Possible solution
A way to fix this issue would be to forward refs in the createMountWrapper HOC:

export default function createMountWrapper(node, options = {}) {
  const { adapter } = options;

  class WrapperComponent extends React.Component {
    // ...
    render() {
      const { Component, forwardedRef } = this.props;
      const { mount, props } = this.state;
      if (!mount) return null;
      return (
        <Component {...props} ref={forwardedRef} />
      );
    }
  }
  // ...
  return React.forwardRef((props, ref) => {
    return <WrapperComponent {...props} forwardedRef={ref} />
  });
)
mount bug package 16 package 16.3

Most helpful comment

Just got hit by this today when testing component by mounting it as root in mount. I had other tests with forwardRef successfully passed though, because I wrapped it under other component.

// this will fail
it('should forward ref to A', () => {
  const ref = React.createRef()
  mount(<BForwarded ref={ref} />)
  expect(ref.current).toBeInstanceOf(A)
});

// while this is a success!
it('should forward ref to A', () => {
  const ref = React.createRef()
  mount(<div><BForwarded ref={ref} /></div>)
  expect(ref.current).toBeInstanceOf(A)
});

So it can be a workaround for now while waiting for the fix

All 9 comments

While that fixes things for your test, it ends up breaking hundreds of other ones :-/

You mean the fix I suggested? It is a breaking change so I understand it might. I'm curious about which hundreds of other tests it might break. I'm saying that because, by not forwarding refs, you'll always get instances of WrappedComponent which is probably useless, I can't believe someone is actually expecting to get those.

I don't think people are directly looking at that instance, but the component stack changes, which means traversals change, etc.

I've added failing tests here: https://github.com/airbnb/enzyme/compare/forward_ref_tests

Just got hit by this today when testing component by mounting it as root in mount. I had other tests with forwardRef successfully passed though, because I wrapped it under other component.

// this will fail
it('should forward ref to A', () => {
  const ref = React.createRef()
  mount(<BForwarded ref={ref} />)
  expect(ref.current).toBeInstanceOf(A)
});

// while this is a success!
it('should forward ref to A', () => {
  const ref = React.createRef()
  mount(<div><BForwarded ref={ref} /></div>)
  expect(ref.current).toBeInstanceOf(A)
});

So it can be a workaround for now while waiting for the fix

Thanks!

@panjiesw Works for me, thanks! A React.Fragment is also sufficient.

Useful to me, thank!

Somehow these tests are passing now, yay!

Awesome o/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

abe903 picture abe903  ยท  3Comments

modemuser picture modemuser  ยท  3Comments

timhonders picture timhonders  ยท  3Comments

AdamYahid picture AdamYahid  ยท  3Comments

blainekasten picture blainekasten  ยท  3Comments