Does ReactJS Compound Pattern violate the DRY principle?

Let’s say we have this component:

const Card = ({ title, description, price, tag, category }) => {
  return (
    <div>
        {title && <h5>{title}</h5>}
        {description && <div>{description}</div>}
        {price && <div>{price}</div>}
        {tag && <div>{tag}</div>}
        {category && <div>{category}</div>}
    </div>
  )
}

With Compound component pattern we can refactor this into:

const Card = ({children}) => <div>{children}</div>
const Title = ({children}) => <h5>{children}</h5>
const Description = ({children}) => <div>{children}</div>
const Price = ({children}) => <div>{children}</div>
const Tag = ({children}) => <div>{children}</div>
const Category = ({children}) => <div>{children}</div>

And usage:

<Card>
    <Title>this is title</Title>
    <Description>description</Description>
    <Price>price</Price>
</Card>

We can easily omit what we don’t need, like Tag and Category in the above example. Now each separated component does only one thing and the parent became clean.

All Good. But doesn’t this violate the DRY principle? Now we have to copy everywhere the ordering logic of the elements.

title > description > price > tag > category > and more in future

If one day we decide to change the order of the elements, category above tag, price above description… it would require changing this everywhere that those components are used. If we don’t want the parent to be responsible for knowing each children it receives, who is responsible to keep the ordering same on each place.

This is simple example with simple layout. But the layout can be way more complex. Like tag and category could share same row (2 columns) or price can be positioned top right. If we use the Compound pattern, who is responsible for keeping the layout same everywhere?

New contributor

Oktay Yuzcan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

2

If the intention of the <Card> component is to have a consistent layout of elements, then it’s not a good fit for the composite pattern. That pattern is suited to cases where different users of the component want different layouts.

So to answer the direct question:

If we use the Compound pattern, who is responsible for keeping the layout same everywhere?

No-one. It is meant to be not the same everywhere.

You wrote about the second example:

We can easily omit what we don’t need, like Tag and Category in the above example.

When I interpret your first example correctly, that function has the same property – so I don’t see any benefits by the second one in regards to this point.

Now each separated component does only one thing and the parent became clean.

This is a pretty common misunderstanding of what “one thing” means. First, to me, your first example is clearly “clean enough” for my taste. Of course, your real component may be more complex and look more convoluted, but the straightforward approach here would be

  • to extract the inner logic of the Card function exactly the way it was to sub-functions for example

    const Title = ({title}) => {title && <h5>{title}</h5>}
    const Description ...
    
  • and then call these subfunctions from the Card function like

    const Card = ({ title, description, price, tag, category }) => {
    return (
      <div>
          {Title(title)}
          {Description(description)}
          {Price(price)}
          {Tag(tag)}
          {Category(category)}
      </div>
     )
    }
    

(forgive me if I did not get the syntax right, I am not a JS coder and definitely not a ReactJS coder, but I guess you get the idea).

Now, the Card function still does “one thing”: it coordinates the calls to the other functions. If you like, you can combine the Card function together with its helper functions into a class.

So to sum this up:

  • yes, your original idea of using the Compound component pattern in the shown way omits the “ordered-output” logic of the original Card function – hence when you implement it that way, it could motivate each caller to implement their own “ordered-output” logic. And in case that’s a logic you want to exist in only one place, it would become a DRY violation

  • the Compound component pattern does not lead to a DRY violation per-se. In case you want users of such components to control the output order by themselves, using the pattern is ok.

  • Implementing this differently without the Compound component pattern will allow to keep the logic in the Card function and extract certain logic to smaller functions.

  • Whether this improves the readability for the very small, artificial example of this question, or not, is quite debatable – but when we assume the original code is more complex, the approach of extracting logic into smaller functions starts definitely making sense.

So in short, implement what you need. If a pattern fits to what you need, fine. If not, implement something different.

2

Only if you have more than one use of card with the same layout.

Let’s say you decide it is a violation of dry and you are going to fix it. But some users want a different order of fields in their cards.

You add a orderBy function to the props to allow this. If it’s not passed in the default order is used.

Your component is slightly better in that less code will be required for multiple usages with the default order. But slightly worse in the unconventional way of specifying the sub components.

The reason react gives you this syntax is so you can make you code look and behave more like HTML. I think people like this.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật