facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
227.82k stars 46.51k forks source link

react-test-renderer: the findByType method doesn't work with memo components #17301

Open bensampaio opened 4 years ago

bensampaio commented 4 years ago

Do you want to request a feature or report a bug? Feature

What is the current behavior? Whenever I try something like:

ReactTestRenderer.create(<SomeComponent />).root.findByType(SomeMemoComponent);

I get the following error: No instances found with node type: "undefined". The only way I found for this to work was to reference the type property of memo components like this:

ReactTestRenderer.create(<SomeComponent />).root.findByType(SomeMemoComponent.type);

I am fine with this solution but then flow complains that type doesn't exist so I find myself fixing this with $FlowFixMe all over the place.

What is the expected behavior?

I would expect that passing a memo component to findByType would work. Or that flow would recognize the type property of memo components. I think both should work, specially the first option.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

No, it never worked as far as I know.

threepointone commented 4 years ago

I think this is a bug, likely fixed by https://github.com/facebook/react/pull/17278

milesj commented 4 years ago

If you debug the result tree, the memo component does not exist, only the component that it wrapped. I believe this is by design? Since the tree is the "reconciled" tree. Would need to dig further.

Edit: Tested on v16.12. The PR above didn't fix this.

bensampaio commented 4 years ago

@milesj indeed, v16.12 didn't fix this problem. If findByType can't work with memo components then I would expect flow to at least recognize the type property of memo components.

ianschmitz commented 4 years ago

I've found a workaround for those that need it.

Pin react, react-dom, react-test-renderer to 16.11.0, and most importantly add a dependency to react-is@16.11.0.

henryqdineen commented 4 years ago

I am having the same issue. One thing that I found is that if SomeMemoComponent.defaultProps is defined it does work as expected. It looks like there is some distinction between MemoComponent and SimpleMemoComponent when building the tree.

martijnsenden commented 4 years ago

Also having this issue. @henryqdineen I tried defining the defaultProps, but that did not help for me.

gaearon commented 4 years ago

See my comment on https://github.com/facebook/react/pull/17700#issuecomment-602738978.

chris-feist commented 4 years ago

I ended up creating my own test predicate until this is resolved:

const MyComponent = () => (<div />);
const MemoMyComponent = React.memo(MyComponent);

const elementByType = (type) => (element) => (
  element.type === type // Match non-memo'd
  || element.type === type.type // Match memo'd
);

const rendered = renderer.create((
  <MyComponent />
));

rendered.root.find(elementByType(MyComponent)) 

const renderedWithMemo = renderer.create((
  <MemoMyComponent />
));

renderedWithMemo.root.find(elementByType(MemoMyComponent))