johannchopin
johannchopin

Reputation: 14873

Using dot notation with functional component

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?

Upvotes: 50

Views: 34260

Answers (4)

GMKHussain
GMKHussain

Reputation: 4719

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

Upvotes: 3

Pawan Kolhe
Pawan Kolhe

Reputation: 111

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>
);

Upvotes: 11

Vandesh
Vandesh

Reputation: 6904

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>
   ....

Upvotes: 20

Dennis Vash
Dennis Vash

Reputation: 53994

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>
);

Upvotes: 81

Related Questions