tdk
tdk

Reputation: 151

Passing undefined component as child using React

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

Answers (2)

JLRishe
JLRishe

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

Hemant Parashar
Hemant Parashar

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

Related Questions