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

React.Lazy always returning the Fallback value #2200

Closed
2 of 13 tasks
philearley opened this issue Jul 22, 2019 · 18 comments · Fixed by #2328
Closed
2 of 13 tasks

React.Lazy always returning the Fallback value #2200

philearley opened this issue Jul 22, 2019 · 18 comments · Fixed by #2328

Comments

@philearley
Copy link

Current behaviour

When writing a test to validate my component is rendered, I am only ever seeing the fallback value.
I am unsure as to what I am doing incorrect or if this is an issue.

import React, { Suspense } from 'react';

const LazyComponent = React.lazy(() => import('./lazy-component-file'));

const ComponentWrapper = () => {
  return (
    <Suspense fallback='...'>
      <LazyComponent />
    </Suspense>
  );
};

export default ComponentWrapper;

....

import { shallow } from 'enzyme';
import React from 'react';

import ComponentWrapper from './component-wrapper';

test('renders the suspense component', () => {
  const wrapper = shallow(<ComponentWrapper />);
  expect(wrapper.find('LazyComponent').length).toEqual(0); // Passes
});

test('renders the LazyComponent', () => {
  const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: false });
  expect(wrapper.find('LazyComponent').length).toEqual(1); // Errors
});

Expected behaviour

I've tried exporting the LazyComponent and doing:
expect(wrapper.find(LazyComponent).length).toEqual(1);

But my issue is flipped on its head and wrapper.find(LazyComponent).length is always 1.

Your environment

API

  • shallow
  • mount
  • render

Version

library version
enzyme 3.10.0
react 16.8.6
react-dom 16.8.6
react-test-renderer 16.8.6
adapter (below) 1.14.0

Adapter

  • enzyme-adapter-react-16
  • enzyme-adapter-react-16.3
  • enzyme-adapter-react-16.2
  • enzyme-adapter-react-16.1
  • enzyme-adapter-react-15
  • enzyme-adapter-react-15.4
  • enzyme-adapter-react-14
  • enzyme-adapter-react-13
  • enzyme-adapter-react-helper
  • others ( )
@ljharb
Copy link
Member

ljharb commented Jul 23, 2019

By default, Lazy in shallow renders the child, but if you pass { suspenseFallback: true } as the second argument to shallow, it should render the fallback.

You can get more info by using wrapper.debug().

@philearley
Copy link
Author

philearley commented Jul 23, 2019

Yeah I was trying to use wrapper.debug() to see the output.

The suspenseFallback option seems to not be making a difference to what is output.

const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: true });
console.log(wrapper.debug());

      <Suspense fallback="...">
        <lazy />
      </Suspense>
const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: false });
console.log(wrapper.debug());

      <Suspense fallback="...">
        <lazy />
      </Suspense>

I would have expected in the second example to see my <LazyComponent /> in place of <lazy />

@ljharb
Copy link
Member

ljharb commented Jul 23, 2019

hmm, that seems like a bug then.

@skyboyer
Copy link
Contributor

skyboyer commented Aug 2, 2019

@philearley does it work to you with mount()? to me it returns fallback as well as shallow() does

@philearley
Copy link
Author

@skyboyer when I tried to use mount I received warnings saying Mount was not supported.

@sergiogeone
Copy link

Hi there, is there any update on the issue? Thanks.

@webdevsyd
Copy link

Still experiencing this issue.

@jbroomer
Copy link

jbroomer commented Jan 31, 2020

@webdevsyd Maybe a little late to the party but I found that I had to dive into my component and then I could find what I was looking for.

const wrapper1 = shallow(<LazyComponent />,  {suspenseFallback: true});
expect(wrapper1.dive().find('FallbackComponent').length).toBe(1);

const wrapper2 = shallow(<LazyComponent />,  {suspenseFallback: false});
expect(wrapper2.dive().find('LazyComponent').length).toBe(1);

@lh0x00
Copy link
Contributor

lh0x00 commented Feb 8, 2020

@webdevsyd Maybe a little late to the party but I found that I had to dive into my component and then I could find what I was looking for.

const wrapper1 = shallow(<LazyComponent />,  {suspenseFallback: true});
expect(wrapper1.dive().find('FallbackComponent').length).toBe(1);

const wrapper2 = shallow(<LazyComponent />,  {suspenseFallback: false});
expect(wrapper2.dive().find('LazyComponent').length).toBe(1);

I created #2328 to resolve this issue and make a note in PR, please read it.

@liegeandlief
Copy link

@lamhieu-vk Has your fix for this issue been released yet? I am on the latest versions of enzyme and enzyme-adapter-react-16 and am still seeing this issue.

@ljharb
Copy link
Member

ljharb commented Aug 6, 2020

@liegeandlief no, the commit that closed the PR shows it's not yet in enzyme-adapter-react-16. i'll cut a release tomorrow.

@ljharb
Copy link
Member

ljharb commented Aug 8, 2020

v1.15.3 of the adapter has been released.

@liegeandlief
Copy link

liegeandlief commented Aug 10, 2020

Unfortunately this still isn't working for me. My test is as follows:

test('it renders as expected', () => {
  const wrapper = shallow(<PageSwitch pageData={{ key: 'home' }} />, { suspenseFallback: true })
  expect(wrapper.find(PageSwitchFallback)).toHaveLength(1)
  expect(wrapper.find(Home)).toHaveLength(0)

  const wrapper2 = shallow(<PageSwitch pageData={{ key: 'home' }} />, { suspenseFallback: false })
  expect(wrapper2.find(PageSwitchFallback)).toHaveLength(0)
  expect(wrapper2.find(Home)).toHaveLength(1)  / * FAILS HERE - expected 1 received 0 */
})

My PageSwitch component is as follows:

const Home = lazy(() => import('../pages/Home/'))

const PageSwitchFallback = memo(() => {
  return <div aria-live='polite' aria-busy /> 
})
PageSwitchFallback.displayName = 'PageSwitchFallback'

const PageSwitch = memo(({ pageData }) => {
  const renderPageComponent = useCallback(() => {
    if (pageData === 'NOT_FOUND') return null

    switch (pageData.key) {
      case 'home':
        return <Home />
    }
  }, [pageData])

  return (
    <Suspense fallback={<PageSwitchFallback />}>
      {renderPageComponent()}
    </Suspense>
  )
})
PageSwitch.displayName = 'PageSwitch'

export default PageSwitch

I have confirmed that it is reaching the home case in the switch block but the test does not seem to find the Home component. The Home component is also memoized and has its displayName property set to Home.

Can you see anything I'm doing wrong here?

@ljharb
Copy link
Member

ljharb commented Aug 12, 2020

What does wrapper2.debug() output?

@liegeandlief
Copy link

It outputs:

<Suspense fallback={{...}} pageData={{...}}>
    <lazy />
</Suspense>

@ljharb
Copy link
Member

ljharb commented Dec 21, 2020

@liegeandlief perhaps it's fixed in latest master - your test cases pass for me. I'll add them to make sure it doesn't regress in the future.

edit: the tests fail in React v16.6 and v16.7. For now, try updating to v16.8 or newer?

@orlandovallejos
Copy link

Well, sadly I have to say that it's still not working for me:

<Suspense fallback={{...}}>
  <lazy defaultCollapsed={false} />
  <lazy defaultCollapsed={false} />
</Suspense>

I'm using the latest version of every package:
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",

@ljharb
Copy link
Member

ljharb commented Feb 20, 2021

@orlandovallejos mind filing a new issue?

web-developer77 added a commit to web-developer77/react-enzyme that referenced this issue Jul 22, 2021
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