50

Official ReactJs documentation recommends to create components following the dot notation like the React-bootstrap library:

<Card>
  <Card.Body>
    <Card.Title>Card Title</Card.Title>
    <Card.Text>
      Some quick example text to build on the card title and make up the bulk of
      the card's content.
    </Card.Text>
  </Card.Body>
</Card>

It is very easy to create this structure with the help of a class component:

const CardBody = ({ children }) => <div className='body'>{children}</div>;

class Card extends Component {
  static Body = CardBody;

  render() {
    return (
      <div className='card'>{this.props.children}</div>
    );
  }
}

But it's also recommended to use as much as possible functional component. Unfortunately I don't know how to achieve this using only functional component.

If I follow this way, I'm no more able to use Card as a component because he is now an object of components:

const Card = {
  Component: CardComponent,
  Body: CardBody
}

export default Card

I'd have to use it that way, and it's not really what I want:

<Card.Component>
  <Card.Body>
  ...

Do you have any idea how to do that?

1
  • 4
    people tend to forget that the class in JS is just syntax sugar for a normal function. Commented Mar 27, 2020 at 9:22

4 Answers 4

81

In function component you can do like so:

// Card.react.js
const Card = ({ children }) => <>{children}</>;
const Body = () => <>Body</>;

Card.Body = Body;
export default Card;

// Usage
import Card from "./Card.react.js";

const App = () => (
  <Card>
    <Card.Body />
  </Card>
);

Or, you can exploit named exports:

// Card.react.js
export const Wrapper = ({ children }) => <>{children}</>;
export const Body = () => <>Body</>;

// Usage
import * as Card from "./Card.react.js";

const App = () => (
  <Card.Wrapper>
    <Card.Body />
  </Card.Wrapper>
);
Sign up to request clarification or add additional context in comments.

5 Comments

Seems to work well with javascript. But I'm using typescript and this one give me a nice error: Property 'Body' does not exist on type 'FunctionComponent<{}>' where FunctionComponent is the type of Card declared like this const Card: React.FunctionComponent = ...
@johannchopin Thats a different question that you should ask
Yeah that's true I did't mention typescript in the question so I will ask a new one ;)
For the curious that saw this question and have trouble typing this code in TypeScript you can have a look at this question: stackoverflow.com/questions/60883388/…
Is it smart to use dot notation with annonymous functional components?
20

For functional components

const CardBody = ({ children }) => <div className='body'>{children}</div>;

const Card = (props) => (
  <div className='card'>{props.children}</div>
);
Card.Body = CardBody

And then use it like

<Card>
  <Card.Body>
   ....

1 Comment

Thanks for your answer it's was just a question of timing for the validation but I upvoted your answer for your time :)
11

Using Functional Components and TypeScript

// Card.tsx
const CardRoot = ({ children }) => <div>{children}</div>;
const CardBody = () => <>Body</>;

export const Card = CardRoot as typeof CardRoot & {
  Body: typeof CardBody;
};
Card.Body = CardBody;

And use like this:

import { Card } from "./Card";

const App = () => (
  <Card>
    <Card.Body />
  </Card>
);

Comments

3

Function component with Table example

// Table.js
import React from 'react'

const Table = (props) => <div className='table'>{props.children}</div>
const Row = ({ children }) => <div className='tr'>{children}</div>
const Cell = ({ children }) => <div className='td'>{children}</div>

Table.Row = Row
Table.Cell = Cell

export default Table
// Something.js
import Table from 'Table.js'

const Something = () => {
  return(<>
    <Table>
      <Table.Row>
        <Table.Cell>Td 1</Table.Cell>
        <Table.Cell>Td 2</Table.Cell>
      </Table.Row>
    </Table>
  </>)
}

export default Something

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.