1

I create a component which is a parent component of another: Container is parent and Container.Data children. In this way I can add a structure to my component.

const Container = ({ children }) => {
  return (
    <div>
      <h1>Container</h1>
      {children}
    </div>
  );
};

const Data = ({ children }) => {
  return <div>{children}</div>;
};

Container.Data = Data;

export { Container };


///

  <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Container>
        <Container.Data>item1</Container.Data>
        <Container.Data>item2</Container.Data>
      </Container>
      <Container.Data>item3</Container.Data>
  </div>

The issue is next: <Container.Data>item3</Container.Data> is outside the component and it works, but I want in the case when I will add the <Container.Data>item3</Container.Data> outside the parent Container, to get an error. So all items should be only inside Container.
Question: How to do this?
demo: https://codesandbox.io/s/stupefied-dubinsky-6lh8v?file=/src/Container.js:27-264

3 Answers 3

2

Use a React Context to create a context for the Data component to "check-in" with. Provide a defaultValue to the context that is overridden by a "real" value by the provider. If a component subscribed to the context doesn't have a matching Provider above it in the tree it uses this default value.

import React from "react";

const ContainerContext = React.createContext("containerless");

const Container = ({ children }) => {
  return (
    <ContainerContext.Provider value="Container">
      <div>
        <h1>Container</h1>
        {children}
      </div>
    </ContainerContext.Provider>
  );
};

const Data = ({ children }) => {
  const containerContext = React.useContext(ContainerContext);

  React.useEffect(() => {
    if (containerContext === "containerless") {
      throw new Error("Data Container not contained in Container component");
    }
  });
  return <div>{children}</div>;
};

Container.Data = Data;

export { Container };

Edit create-a-component-as-a-children-of-another-in-react-js

App

Move the "item3" data container in and out of Container to test.

function App() {
  return (
    <div className="App">
      <Container>
        <Container.Data>item1</Container.Data>
        <Container.Data>item2</Container.Data>
      </Container>
      <Container.Data>item3</Container.Data>
    </div>
  );
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can pass the extra param in children of container and check in Data component that if that component has the prop or not. If it does not then ignore the child.

import React from "react";

const Container = ({ children }) => {
  return (
    <div className="parent-container">
      <h1>Container</h1>
      {React.Children.map(children, (child, i) => {
        return React.cloneElement(child, {
          fromParent: true
        });
      })}
    </div>
  );
};

const Data = ({ children, fromParent }) => {
  if (!fromParent) {
    return null;
  }
  return <div>{children}</div>;
};

Container.Data = Data;

export { Container };

https://codesandbox.io/s/naughty-elion-42ppn?file=/src/Container.js:0-474

Comments

0

In order to achieve better readability, I would suggest having each element structured in different files and then importing them when needed like so:

import Container from './Container';

Then you'll be able to use them in your App file without problems.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.