-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Question: How to know if the loading status of Suspense resolved #14577
Comments
The existing introspection is already flaky and is painful to maintain. I don't think extending that to guess Suspense state from Fibers is something we'd want to support even as a temporary measure. We need to seriously rethink the testing strategy going forward. |
After some discussion in enzymejs/enzyme#1917 I think we will not rush to build an api for waiting lazy component loading. But this is still worth to do.
// in component
// when `React.lazy` called it will cache the returned component
const LazyComponent = React.lazy(() => import("./DynamicComponent"))
// in test
// in `preloadLazy` we check if the passed component(s) is as same as the component(s) we've seen before, If so we'll preload it.
await React.preloadLazy(LazyComponent)
// will render DynamicComponent inside Suspense in initial mount
ReactDOM.render(<Suspense fallback={<Fallback />}>
<LazyComponent />
</Suspense>) |
The whole notion of "waiting" for Suspense in tests is suspicious to me. Your components are available synchronously so why wait (unless you specifically test the placeholder)? If the issue is with React not giving you a mechanism maybe #14626 can fix it. |
Thanks for reply and this looks good! I think it would be helpful in some cases. // in LazyComponent.js
const LazyComponent = React.lazy(() => import("./InternalComponent"))
// in some component using LazyComponent
const ComponentToTest = () => {
return (<Suspense fallback={<Fallback />}>
<LazyComponent />
</Suspense)
}
// in test code testing(rendering) `ComponentToTest` how could we pass the synchronous version of `LazyComponent` into `ComponentToTest`? I know we can make // in ComponentToTest.js
const ComponentToTest = (props) => {
const { LazyComponentProp } = props
return (<Suspense fallback={<Fallback />}>
<LazyComponentProp />
</Suspense)
}
// in test code we can pass InternalComponent directly
testRender.render(<ComponentToTest LazyComponentProp={InternalComponent} />) But if we have many lazy components inside I think in such case if we can something diretly set const LazyComponent = React.lazy(() => import("./InternalComponent"))
// in test code
LazyComponent.setLoadedComponent(InternalComponent)
// So In test code(or future rendering) react will view LazyComponent as loaded InternalComponent I'm not sure if I miss anything here, though. |
Or, is it possible to reset the dynamic loading function into lazy compoment so we can make it load the synchronous thenable in test env? Example: const LazyComponent = React.lazy(() => import("./InternalComponent")
// replace passed loader func with sync one
LazyComponent.resetLoader(() => { then() { return InternalComponent } }) |
Ah, I found out that to test lazy synchronously we can just handle it with mock utility in jest or sinon, no need to have // in LazyComponent.js
const LazyComponent = React.lazy(() => import("./InternalComponent"))
// in some component using LazyComponent
const ComponentToTest = () => {
return (<Suspense fallback={<Fallback />}>
<LazyComponent />
</Suspense)
}
// in test code (using jest)
beforeAll(() => {
jest.mock('/path/to/LazyComponent', () => InternalComponent) // or pass synchronous thenable to React.lazy
})
// will render ComponentToTest with InternalComponent in initial mount.
const ComponentToTest = require('./ComponentToTest')
ReactDOM.render(<ComponentToTest />) Still thanks for discussion :) |
Node doesn't have |
Hi @gaearon and @chenesan , am using lazy and Suspense to dynamically load and display a component in my App, and it works fine. But when testing the component using jest and enzyme, am getting the error:
I also tried with react-test-renderer
And they both give same error. I have used the line below from the documentation in react: https://reactjs.org/docs/code-splitting.html Edit: |
@chenesan This is great! Was banging my head about this for a while, just had to make sure
|
I'm too having this testing issue,Simply my problem is, How to test components with I couldn't understand how @gaearon's #14626 PR could help to solve this testing issue? |
I needed to test my lazy component using Enzyme. For now, following worked for me to test on component loading completion:
Test Code ->
This is hacky but working well for Enzyme library. |
Do you want to request a feature or report a bug?
Question
What is the current behavior?
I'm trying to implement supports of
React.lazy
andReact.Suspense
in enzyme (enzymejs/enzyme#1975). I'd like to have something likewaitUntilLazyLoaded
so we can write such test:Inside the
mount
implementation we call theReactDOM.render
to render it and get the root fiber node. Now my problem is: Given a Fiber node ofSuspense
, how could we know the loading status ofSuspense
so I can make sure whether (1) the module is loaded successfully loaded (or failed) and (2) React has rendered (or not rendered) the new component tree?I'm not familiar with the implementation detail of Fiber and I'm still trying to investigate into this. That would be great if someone familiar with this could answer. Thanks!
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
^16.6
The text was updated successfully, but these errors were encountered: