I want to conditionally import a React Component if the file exists and if not do something else. For example show a default view or message.
I tried this:
let Recipe;
try {
Recipe = require(`docs/app/Recipes/${props.componentName}`);
} catch (e) {
Recipe = () => <div>Not found</div>;
}
However the linter is complaining that I should not try to dynamicaly require a file, but use a string literal instead.
Is there a cleaner approach to to what I'm trying to achieve?
In React, dynamically importing a component is easy—you invoke React. lazy with the standard dynamic import syntax and specify a fallback UI. When the component renders for the first time, React will load that module and swap it in.
The React is imported as default import and renders as named import.
1 Answer. Show activity on this post. You no longer need to import React from "react" . Starting from the release 17 of React, JSX is automatically transformed without using React.
lazy(() => import('./OtherComponent')); This will automatically load the bundle containing the OtherComponent when this component is first rendered. React. lazy takes a function that must call a dynamic import() .
The problem is this approach is that it kills bundle optimizations and includes all files from docs/app/Recipes/
into a bundle, even if they aren't used.
A better way to write this is to use <React.Suspense>
and React.lazy
:
const Recipe = React.lazy(() =>
import(`docs/app/Recipes/${props.componentName}`)
.catch(() => ({ default: () => <div>Not found</div> }))
);
Which is used as:
<React.Suspense fallback={'loading...'}><Recipe/></React.Suspense>
A cleaner way to do this and avoid linter error is to have a map of possible components:
import Foo from 'docs/app/Recipes/Foo';
import Bar from 'docs/app/Recipes/Bar';
...
const componentsMap = { Foo, Bar };
...
const Recipe = componentsMap[props.componentName] || () => <div>Not found</div>;
In this case props.componentName
can be validated if needed.
in fact there is. With the recent release of React v16.6.0 "lazy code splitting" was introduced. This is how it works, it makes sense to use it together with reacts' 'suspense':
import React, {lazy, Suspense} from 'react';
const Recipe = lazy(() =>import(`./docs/app/Recipes/${props.componentName}`));
function SomeComponent() {
return (
<Suspense fallback={<Spinner/>}>
<Recipe />
</Suspense>
);
}
To handle the case that the component isn't found you can use Error Boundaries. You would wrap your component with it like this:
<ErrorBoundary>
<Suspense fallback={<Spinner/>}>
<Recipe />
</Suspense>
</ErrorBoundary>
Best you read more about it directly on the react docs I linked above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With