Reputation: 151
I think code explains it better than words. So, this is what I am trying to do:
import { useEffect, useState } from "react";
import "./styles.css";
const IAmHiComponent = ({ children }) => <div>{children}</div>;
const COMPONENTS = {
hi: IAmHiComponent
};
const Boom = ({ isLoaded, children }) => {
if (!isLoaded) {
return "Loading...";
}
return <div style={{ background: "red" }}>{children}</div>;
};
export default function App() {
const [loadedComponent, setLoadedComponent] = useState(null);
useEffect(() => {
setTimeout(() => {
setLoadedComponent("hi");
}, 5000);
}, []);
const MyLoadedComponent = COMPONENTS[loadedComponent];
return (
<Boom isLoaded={!!loadedComponent}>
<MyLoadedComponent>Hi!!!</MyLoadedComponent>
</Boom>
);
}
https://codesandbox.io/s/cocky-benz-3nxy2?file=/src/App.js
it's simplified version, but basically what I am trying to do is to pass initially undefined
component as a child and have kind of loading check in parent component and render children
only when I know that everything is loaded.
And everything is working fine, but React is not happy about my approach and I am getting this error:
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
So I am trying to understand am I doing something terribly wrong? or just missing something small?
Upvotes: 0
Views: 308
Reputation: 101690
Looks like you can simply conditionally include the child component:
export default function App() {
const [loadedComponent, setLoadedComponent] = useState(null);
useEffect(() => {
setTimeout(() => {
setLoadedComponent("hi");
}, 5000);
}, []);
const MyLoadedComponent = COMPONENTS[loadedComponent];
return (
<Boom isLoaded={!!loadedComponent}>
{ loadedComponent ? <MyLoadedComponent>Hi!!!</MyLoadedComponent> : null }
</Boom>
);
}
Upvotes: 1
Reputation: 3774
You're trying to access null
on COMPONENTS
which gives undefined
when loadedComponent
is initially null.
You can add a check to only render the component when loadedComponent
is not null like so :
export default function App() {
const [loadedComponent, setLoadedComponent] = useState(null);
useEffect(() => {
setTimeout(() => {
setLoadedComponent("hi");
}, 5000);
}, []);
const MyLoadedComponent = COMPONENTS[loadedComponent];
return (
<Boom isLoaded={!!loadedComponent}>
{loadedComponent ? <MyLoadedComponent>Hi!!!</MyLoadedComponent> : null }
</Boom>
);
}
Upvotes: 0