Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot find a function component wrapped with React.memo HOC #2038

Closed
papiro opened this issue Mar 7, 2019 · 11 comments · Fixed by #2081
Closed

Cannot find a function component wrapped with React.memo HOC #2038

papiro opened this issue Mar 7, 2019 · 11 comments · Fixed by #2081

Comments

@papiro
Copy link

papiro commented Mar 7, 2019

Current behavior

When trying to .find a memoized function component within a mounted tree and .debug it, returns an empty string.
This is regarding the new React.memo feature. When I simply remove the React.memo wrapper from the component, then it is found and its contents printed to the console on .debug. With the wrapper, it appears the component cannot be found.

Expected behavior

Should output the component.

Your environment

Windows 10, GitBash, Jest

API

  • [x ] mount

Version

library version
enzyme 3.9.0
react 16.8.3
react-dom 16.8
react-test-renderer 16.8.4
adapter (below) 1.10.0

Adapter

  • [x ] enzyme-adapter-react-16
@ljharb
Copy link
Member

ljharb commented Mar 9, 2019

@papiro can you provide repro code? Specifically, your component, your test code, and wrapper.debug() on the root wrapper?

@papiro
Copy link
Author

papiro commented Mar 11, 2019

Phew! That sure would be a lot of code. Lots of components involved, along with the app-environment stubbed out via test-helper HOCs and the lot. I'll try to shuck off what's not needed to reproduce.

@mliq
Copy link

mliq commented Mar 20, 2019

I have the same issue, here is a repro:
https://github.com/mliq/enzyme-memo-bug-repro

@mliq
Copy link

mliq commented Mar 20, 2019

@ljharb

wrapper.debug() on component without React.memo HOC:

<Button className="mockClass">
  <button className="mockClass">
     mockContent
  </button>
</Button>

wrapper.debug() on component with React.memo HOC:

<Button className="mockClass" />

@nicotaing
Copy link

nicotaing commented Mar 21, 2019

I'm running into a some sort of similar issue with enzyme-adapter-react-16 1.11.2

Using the constructor to find children won't work but using the display name will work

Here's an example:

// Child.js
import React, { Fragment, memo } from 'react';

function Child() {
    return <Fragment>Child</Fragment>;
}

export default memo(Child);
// Parent.js
import React, { memo } from 'react';
import Child from './Child';

function Parent() {
    return (
        <div>
            <Child />
            <Child />
        </div>
    );
};

export default memo(Parent);
import React from 'react';
import { mount } from 'enzyme';
import Parent from './Parent';
import Child from './Child';

const parent = mount(<Parent />);

console.log(parent.debug()); 
// Returns the right nodes
// <Parent>
//     <Child />
//     <Child />
// </Parent>

console.log(parent.find(Child).debug());
// Returns nothing

console.log(parent.find('Child').debug());
// Return the right nodes
//   <Child />
//   <Child />

@eps1lon
Copy link
Contributor

eps1lon commented Mar 21, 2019

Encountered the same issue today. React.memo will also not appear in the component tree from debug(): https://codesandbox.io/s/94v1m6p21o

@ljharb
Copy link
Member

ljharb commented Mar 22, 2019

I'll confirm whether it should appear in the debug tree or not; either way, finding by constructor should definitely work.

@Nerlin
Copy link

Nerlin commented Mar 29, 2019

Affects my code too, can't add React.memo to my functional components because tests fail to find wrapped component children.

@lfender6445
Copy link

lfender6445 commented Aug 15, 2019

When I wrap with memo, I get a shape that looks like this

    { '$$typeof': Symbol(react.memo),
      type:
       { [Function: Foo]
         displayName: 'Foo',
         defaultProps: { theme: {} } },
      compare: null }

so in my jest test, i can get the inner component by referencing the type key

import MemoizedFoo from './Foo'
const Foo = MemoizedFoo.type

describe() { it() { shallow(Foo) ...etc } }

This is great for shallow unit tests.

If i was mounting a parent component and looking for children to be present, you could do something like this:

wrapper = mount(Layout)
wrapper.find('Memo(Foo)')

@ahmedlhanafy
Copy link

Setting the display name property on the memoized component solved the problem for me.

const TextBase = (props) => {...};

export const Text = React.memo(TextBase);

Text.displayName = 'Text';

@SQReder
Copy link

SQReder commented Dec 5, 2019

I have a similar issue when using non-default export, wich not been memoized.

// Foo.tsx
export const Foo(props) {...};
export default memo(Foo);


// Foo.tests.tsx
import { Foo } from "./Foo"; // should be default import, but no 😕

const wrapper = mount(<FooWrapper />);

wrapper.find(Foo)

So I just changed import to use default exported memoized component and the issue has gone.

react-scripts: 3.3.0
enzyme: 3.1.0
jest-enzyme: 7.1.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants