anshul
anshul

Reputation: 791

Attaching React functional components in compound pattern?

I am building a React component using the compound pattern as follows:

import React from "react";

function Card({ children }) {
  return <div>{children}</div>;
}

function Heading({ children }) {
  return <h2>{children}</h2>;
}

export Heading;
export default Card;

I'm not sure why I cannot use the export as above. However when I do

Card.Heading = Heading;
export default Card;

I'm now able to consume as follows:

<Card>
  <Card.Heading>hello</Card.Heading>
</Card>

I am trying to find out why Card.Heading = Heading is working as expected. Is it valid to attach react components using dot[.] notation like how I did?

Upvotes: 1

Views: 222

Answers (3)

Borni.Mr
Borni.Mr

Reputation: 679

You can use arrow function, this should fix your issue.

import React from "react";

function Card({ children }) {
  return <div>{children}</div>;
}

export const Heading = ({ children }) => {
  return <h2>{children}</h2>;
}

export default Card;

When importing from other file:

import Card, { Heading } from 'file emplacement';

Upvotes: 0

Youssouf Oumar
Youssouf Oumar

Reputation: 46141

Your first attempt is not working, because you didn't attach Card to Heading before exporting. An export don't attach them, in fact you would import them like so (I assume we are in a file called Components.js):

import Card {Heading} from "Components";

That has been said, because a component should be independent, you shouldn't be (even if it is valid, since functions are objects in JavaScript) attaching them like this for readability:

Card.Heading = Heading;

If you wanna consume different components as one with proprieties, you would do something like this:

function Card({ children }) {
  return <div>{children}</div>;
}

function Heading({ children }) {
  return <h2>{children}</h2>;
}

export Heading;
export Card;
// or 
/*
export default {
  Heading
  Card
}*/

Then where you need those components, you do this:

import * as Component from "Components" // for the first export
// import Component from "Components" // for the second one;

function App({ children }) {
  return(
  <Component.Card>
      <Component.Header />
      {children}
  
  </Component.Card>;)
}

export default App;

Upvotes: 1

rxjmx
rxjmx

Reputation: 2181

I would assume this is a valid pattern.

Since React components are functions and functions are first-class objects, it's valid to assign properties like you have done. See the excerpt here.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions

As far as importing Card if you wanted to use Card in another file you'd need to do the following.

import Card from './Card' since it's the default export.

Alternatively you could change the export to looks something like this.

export default {
 Heading,
 Card
}

Upvotes: 1

Related Questions